From d4846a6296c7b538001c51df984800c130a09c57 Mon Sep 17 00:00:00 2001 From: Alexander Danilov Date: Thu, 27 Jun 2019 10:28:12 +0300 Subject: [PATCH 1/6] Fix Sync of uniques #165 --- plugins/sync.user.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/sync.user.js b/plugins/sync.user.js index 8f1c3ca0e..c4774cd7b 100644 --- a/plugins/sync.user.js +++ b/plugins/sync.user.js @@ -203,21 +203,22 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { _this.initialized = true; _this.initializing = false; plugin.sync.logger.log('Data loaded: ' + _this.pluginName + '[' + _this.fieldName + ']'); - if(callback) callback(); + if(_this.callback) _this.callback(); if(_this.initializedCallback) _this.initializedCallback(_this.pluginName, _this.fieldName); }; // Stop the sync if any error occur and try to re-authorize handleError = function(e) { - var error_type = e.type; + var isNetworkError = e.type; + var errorMessage = (e.error !== undefined) ? e.error.message : e.result.error.message; - if(e.error.message === "A network error occurred, and the request could not be completed.") { - error_type = "network error"; + if(errorMessage === "A network error occurred, and the request could not be completed.") { + isNetworkError = true; } - plugin.sync.logger.log('Drive API Error: ' + error_type); + plugin.sync.logger.log('Drive API Error: ' + errorMessage); _this.stopSync(); - if(error_type === "network error") { + if(isNetworkError === true) { setTimeout(function() {_this.authorizer.authorize();}, 50*1000); } else if(e.status === 401) { // Unauthorized _this.authorizer.authorize(); @@ -225,7 +226,7 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { _this.forceFileSearch = true; _this.initFile() } else { - alert('Plugin Sync error: ' + error_type + ', ' + e.message); + alert('Plugin Sync error: ' + errorMessage + ', ' + e.message); } }; From 4cca73541825f5f9b7c1c3c99dd0370f742e4129 Mon Sep 17 00:00:00 2001 From: Alexander Danilov Date: Thu, 27 Jun 2019 10:29:54 +0300 Subject: [PATCH 2/6] Removed an unnecessary timer that duplicates a repeated connection attempt in case of a network error --- plugins/sync.user.js | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/plugins/sync.user.js b/plugins/sync.user.js index c4774cd7b..2cea9a01f 100644 --- a/plugins/sync.user.js +++ b/plugins/sync.user.js @@ -217,7 +217,6 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { } plugin.sync.logger.log('Drive API Error: ' + errorMessage); - _this.stopSync(); if(isNetworkError === true) { setTimeout(function() {_this.authorizer.authorize();}, 50*1000); } else if(e.status === 401) { // Unauthorized @@ -232,16 +231,6 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { this.dataStorage.readFile(initializeFile, onFileLoaded, handleError); }; - -window.plugin.sync.RegisteredMap.prototype.stopSync = function() { - clearInterval(this.intervalID); - this.intervalID = null; - this.map = null; - this.lastUpdateUUID = null; - this.initializing = false; - this.initialized = false; - plugin.sync.registeredPluginsFields.addToWaitingInitialize(this.pluginName, this.fieldName); -}; //// end RegisteredMap @@ -277,19 +266,6 @@ window.plugin.sync.RegisteredPluginsFields.prototype.add = function(registeredMa this.initializeWorker(); }; -window.plugin.sync.RegisteredPluginsFields.prototype.addToWaitingInitialize = function(pluginName, fieldName) { - var registeredMap, _this; - _this = this; - - registeredMap = this.get(pluginName, fieldName); - if(!registeredMap) return; - this.waitingInitialize[registeredMap.getFileName()] = registeredMap; - - clearTimeout(this.timer); - this.timer = setTimeout(function() {_this.initializeWorker()}, 10000); - plugin.sync.logger.log('Retry in 10 sec.: ' + pluginName + '[' + fieldName + ']'); -}; - window.plugin.sync.RegisteredPluginsFields.prototype.get = function(pluginName, fieldName) { if(!this.pluginsfields[pluginName]) return; return this.pluginsfields[pluginName][fieldName]; From d55a4ae9b2d69c41eb5be73453aa75d63bc075b1 Mon Sep 17 00:00:00 2001 From: Alexander Danilov Date: Thu, 27 Jun 2019 10:37:06 +0300 Subject: [PATCH 3/6] Change the display of the change log. Only the last message is shown for each synchronized file. --- plugins/sync.user.js | 63 ++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/plugins/sync.user.js b/plugins/sync.user.js index 2cea9a01f..f575cedcf 100644 --- a/plugins/sync.user.js +++ b/plugins/sync.user.js @@ -2,7 +2,7 @@ // @id iitc-plugin-sync@xelio // @name IITC plugin: Sync // @category Misc -// @version 0.3.1.@@DATETIMEVERSION@@ +// @version 0.4.0.@@DATETIMEVERSION@@ // @description [@@BUILDNAME@@-@@BUILDDATE@@] Sync data between clients via Google Drive API. Only syncs data from specific plugins (currently: Keys, Bookmarks). Sign in via the 'Sync' link. Data is synchronized every 3 minutes. @@METAINFO@@ // ==/UserScript== @@ -142,7 +142,7 @@ window.plugin.sync.RegisteredMap.prototype.initFile = function(callback) { failedCallback = function(resp) { _this.initializing = false; _this.failed = true; - plugin.sync.logger.log('Could not create file: ' + _this.getFileName() + '. If this problem persist, delete this file in IITC-SYNC-DATA-V3 in your Google Drive and try again.'); + plugin.sync.logger.log(_this.getFileName(), 'Could not create file. If this problem persist, delete this file in IITC-SYNC-DATA-V3 in your Google Drive and try again.'); }; this.dataStorage = new plugin.sync.DataManager({'fileName': this.getFileName(), @@ -174,7 +174,7 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { }); _this.dataStorage.saveFile(_this.prepareFileData()); - plugin.sync.logger.log('Model initialized: ' + _this.pluginName + '[' + _this.fieldName + ']'); + plugin.sync.logger.log(_this.getFileName(), 'Model initialized'); }; // this function called when the document is loaded @@ -192,7 +192,7 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { // Replace local value if data is changed by others if(_this.isUpdatedByOthers()) { - plugin.sync.logger.log('Updated by others, replacing content: ' + _this.pluginName + '[' + _this.fieldName + ']'); + plugin.sync.logger.log(_this.getFileName(), 'Updated by others, replacing content'); window.plugin[_this.pluginName][_this.fieldName] = {}; $.each(_this.map, function(key, value) { window.plugin[_this.pluginName][_this.fieldName][key] = _this.map[key]; @@ -202,7 +202,7 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { _this.initialized = true; _this.initializing = false; - plugin.sync.logger.log('Data loaded: ' + _this.pluginName + '[' + _this.fieldName + ']'); + plugin.sync.logger.log(_this.getFileName(), 'Data loaded'); if(_this.callback) _this.callback(); if(_this.initializedCallback) _this.initializedCallback(_this.pluginName, _this.fieldName); }; @@ -216,7 +216,7 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { isNetworkError = true; } - plugin.sync.logger.log('Drive API Error: ' + errorMessage); + plugin.sync.logger.log(_this.getFileName(), errorMessage); if(isNetworkError === true) { setTimeout(function() {_this.authorizer.authorize();}, 50*1000); } else if(e.status === 401) { // Unauthorized @@ -341,7 +341,7 @@ window.plugin.sync.DataManager.prototype.initialize = function(force, assignIdCa this.force = force; // throw error if too many retry if(this.retryCount >= this.RETRY_LIMIT) { - plugin.sync.logger.log('Too many file operation: ' + this.fileName); + plugin.sync.logger.log(this.fileName, 'Too many file operation'); failedCallback(); return; } @@ -369,7 +369,7 @@ window.plugin.sync.DataManager.prototype.initFile = function(assignIdCallback, f handleFailed = function(resp) { _this.fileId = null; _this.saveFileId(); - plugin.sync.logger.log('File operation failed: ' + (resp.error || 'unknown error')); + plugin.sync.logger.log(_this.fileName, 'File operation failed: ' + (resp.error || 'unknown error')); failedCallback(resp); }; @@ -404,7 +404,7 @@ window.plugin.sync.DataManager.prototype.initParent = function(assignIdCallback, parentAssignIdCallback = function(id) { plugin.sync.parentFolderID = id; - plugin.sync.logger.log('Parent folder success initialized'); + plugin.sync.logger.log('all', 'Parent folder success initialized'); if (plugin.sync.parentFolderIDrequested) { plugin.sync.parentFolderIDrequested = false; return; @@ -415,7 +415,7 @@ window.plugin.sync.DataManager.prototype.initParent = function(assignIdCallback, parentFailedCallback = function(resp) { plugin.sync.parentFolderID = null; plugin.sync.parentFolderIDrequested = false; - plugin.sync.logger.log('Create folder operation failed: ' + (resp.error || 'unknown error')); + plugin.sync.logger.log('all', 'Create folder operation failed: ' + (resp.error || 'unknown error')); failedCallback(resp); }; @@ -574,13 +574,13 @@ window.plugin.sync.Authorizer.prototype.authorize = function(redirect) { handleAuthResult = function(authResult) { if(authResult && !authResult.error) { _this.authorized = true; - plugin.sync.logger.log('Authorized'); + plugin.sync.logger.log('all', 'Authorized'); } else { _this.authorized = false; var error = (authResult && authResult.error) ? authResult.error : 'not authorized'; - plugin.sync.logger.log('Authorization error: ' + error); + plugin.sync.logger.log('all', 'Authorization error: ' + error); if (error === "idpiframe_initialization_failed") { - plugin.sync.logger.log('You need enable 3rd-party cookies in your browser or allow [*.]google.com'); + plugin.sync.logger.log('all', 'You need enable 3rd-party cookies in your browser or allow [*.]google.com'); } } _this.authComplete(); @@ -599,7 +599,7 @@ window.plugin.sync.Authorizer.prototype.authorize = function(redirect) { if(isSignedIn) { _this.authorized = true; - plugin.sync.logger.log('Authorized'); + plugin.sync.logger.log('all', 'Authorized'); } else { _this.authorized = false; @@ -621,25 +621,32 @@ window.plugin.sync.Authorizer.prototype.authorize = function(redirect) { window.plugin.sync.Logger = function(options) { this.logLimit = options['logLimit']; this.logUpdateCallback = options['logUpdateCallback']; - this.logs = []; + this.logs = {}; this.log = this.log.bind(this); this.getLogs = this.getLogs.bind(this); }; -window.plugin.sync.Logger.prototype.log = function(message) { - var log = {'time': new Date(), 'message': message}; - this.logs.unshift(log); - if(this.logs.length > this.logLimit) { - this.logs.pop(); +window.plugin.sync.Logger.prototype.log = function(filename, message) { + var entity = {'time': new Date(), 'message': message}; + + if (filename === 'all') { + Object.keys(this.logs).forEach((key) => { + this.logs[key] = entity; + }); + } else { + this.logs[filename] = entity; } + if(this.logUpdateCallback) this.logUpdateCallback(this.getLogs()); }; window.plugin.sync.Logger.prototype.getLogs = function() { var allLogs = ''; - $.each(this.logs, function(ind,log) { - allLogs += log.time.toLocaleTimeString() + ': ' + log.message + '
'; + Object.keys(this.logs).forEach((key) => { + var value = this.logs[key]; + allLogs += '

'+key+':

' + value.message+' ('+value.time.toLocaleTimeString()+')

'; }); + return allLogs; }; @@ -755,6 +762,18 @@ window.plugin.sync.setupCSS = function() { white-space: -o-pre-wrap;\ word-wrap: break-word;\ overflow-y: auto;\ + }\ + .sync-log-block {\ + background: #ffffff1a;\ + padding: 5px;\ + margin: 0.5em 0;\ + }\ + .sync-log-file {\ + margin: 0;\ + }\ + .sync-log-message {\ + margin: 0;\ + text-align: right;\ }") .appendTo("head"); }; From 85d5443d7ccade0d8bc0d30e69f99d956f3321ad Mon Sep 17 00:00:00 2001 From: Alexander Danilov Date: Thu, 27 Jun 2019 11:55:02 +0300 Subject: [PATCH 4/6] Fix of the first synchronization --- plugins/sync.user.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/plugins/sync.user.js b/plugins/sync.user.js index f575cedcf..6b852075d 100644 --- a/plugins/sync.user.js +++ b/plugins/sync.user.js @@ -41,6 +41,8 @@ window.plugin.sync.authorizer = null; window.plugin.sync.registeredPluginsFields = null; window.plugin.sync.logger = null; +window.plugin.sync.checkInterval = 3 * 60 * 1000; // update data every 3 minutes + // Other plugin call this function to push update to Google Drive API // example: // plugin.sync.updateMap('keys', 'keysdata', ['guid1', 'guid2', 'guid3']) @@ -175,6 +177,7 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { _this.dataStorage.saveFile(_this.prepareFileData()); plugin.sync.logger.log(_this.getFileName(), 'Model initialized'); + setTimeout(function() {_this.loadDocument();}, window.plugin.sync.checkInterval); }; // this function called when the document is loaded @@ -187,7 +190,7 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { if (!_this.intervalID) { _this.intervalID = setInterval(function() { _this.loadDocument(); - }, 3 * 60 * 1000); // update data every 3 minutes + }, window.plugin.sync.checkInterval); } // Replace local value if data is changed by others @@ -223,7 +226,8 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { _this.authorizer.authorize(); } else if(e.status === 404) { // Not found _this.forceFileSearch = true; - _this.initFile() + _this.initFile(); + setTimeout(function() {_this.loadDocument();}, window.plugin.sync.checkInterval); } else { alert('Plugin Sync error: ' + errorMessage + ', ' + e.message); } From 4d9c8be9d7e28fdc25eefcbf2d4b3cfbb4c82b60 Mon Sep 17 00:00:00 2001 From: Alexander Danilov Date: Wed, 16 Oct 2019 17:53:27 +0300 Subject: [PATCH 5/6] fix https://github.com/IITC-CE/ingress-intel-total-conversion/issues/226 Disable error output with alert() --- plugins/sync.user.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/sync.user.js b/plugins/sync.user.js index 6b852075d..d41f35e8b 100644 --- a/plugins/sync.user.js +++ b/plugins/sync.user.js @@ -228,8 +228,6 @@ window.plugin.sync.RegisteredMap.prototype.loadDocument = function(callback) { _this.forceFileSearch = true; _this.initFile(); setTimeout(function() {_this.loadDocument();}, window.plugin.sync.checkInterval); - } else { - alert('Plugin Sync error: ' + errorMessage + ', ' + e.message); } }; From 13c52985368bdc7d10c007af53edfcb48ce50c4b Mon Sep 17 00:00:00 2001 From: Alexander Danilov Date: Wed, 16 Oct 2019 17:59:34 +0300 Subject: [PATCH 6/6] add 'uniques' to sync description --- plugins/sync.user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/sync.user.js b/plugins/sync.user.js index d41f35e8b..691728085 100644 --- a/plugins/sync.user.js +++ b/plugins/sync.user.js @@ -3,7 +3,7 @@ // @name IITC plugin: Sync // @category Misc // @version 0.4.0.@@DATETIMEVERSION@@ -// @description [@@BUILDNAME@@-@@BUILDDATE@@] Sync data between clients via Google Drive API. Only syncs data from specific plugins (currently: Keys, Bookmarks). Sign in via the 'Sync' link. Data is synchronized every 3 minutes. +// @description [@@BUILDNAME@@-@@BUILDDATE@@] Sync data between clients via Google Drive API. Only syncs data from specific plugins (currently: Keys, Bookmarks, Uniques). Sign in via the 'Sync' link. Data is synchronized every 3 minutes. @@METAINFO@@ // ==/UserScript==