Add "Stop Sync" button
Stops all syncing (not just file syncing like in 4.0) as soon as possible.
This commit is contained in:
parent
7729dcafc0
commit
1da18e4ca7
9 changed files with 134 additions and 42 deletions
|
@ -112,6 +112,7 @@
|
||||||
max-width: 28px;
|
max-width: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#zotero-tb-sync-stop .toolbarbutton-icon,
|
||||||
#zotero-tb-sync-error .toolbarbutton-icon {
|
#zotero-tb-sync-error .toolbarbutton-icon {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,6 +282,7 @@ Zotero.Sync.Storage.Engine.prototype.start = Zotero.Promise.coroutine(function*
|
||||||
|
|
||||||
|
|
||||||
Zotero.Sync.Storage.Engine.prototype.stop = function () {
|
Zotero.Sync.Storage.Engine.prototype.stop = function () {
|
||||||
|
Zotero.debug("Stopping file syncing for " + this.library.name);
|
||||||
for (let type in this.queues) {
|
for (let type in this.queues) {
|
||||||
this.queues[type].stop();
|
this.queues[type].stop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,6 @@ Zotero.Sync.Data.Engine = function (options) {
|
||||||
this.libraryID = options.libraryID;
|
this.libraryID = options.libraryID;
|
||||||
this.library = Zotero.Libraries.get(options.libraryID);
|
this.library = Zotero.Libraries.get(options.libraryID);
|
||||||
this.libraryTypeID = this.library.libraryTypeID;
|
this.libraryTypeID = this.library.libraryTypeID;
|
||||||
this.requests = [];
|
|
||||||
this.uploadBatchSize = 25;
|
this.uploadBatchSize = 25;
|
||||||
this.uploadDeletionBatchSize = 50;
|
this.uploadDeletionBatchSize = 50;
|
||||||
|
|
||||||
|
@ -93,6 +92,8 @@ Zotero.Sync.Data.Engine.prototype.start = Zotero.Promise.coroutine(function* ()
|
||||||
this.libraryTypeID = info.userID;
|
this.libraryTypeID = info.userID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._statusCheck();
|
||||||
|
|
||||||
// Check if we've synced this library with the current architecture yet
|
// Check if we've synced this library with the current architecture yet
|
||||||
var libraryVersion = this.library.libraryVersion;
|
var libraryVersion = this.library.libraryVersion;
|
||||||
if (!libraryVersion || libraryVersion == -1) {
|
if (!libraryVersion || libraryVersion == -1) {
|
||||||
|
@ -101,6 +102,8 @@ Zotero.Sync.Data.Engine.prototype.start = Zotero.Promise.coroutine(function* ()
|
||||||
libraryVersion = this.library.libraryVersion;
|
libraryVersion = this.library.libraryVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._statusCheck();
|
||||||
|
|
||||||
// Perform a full sync if necessary, passing the getVersions() results if available.
|
// Perform a full sync if necessary, passing the getVersions() results if available.
|
||||||
//
|
//
|
||||||
// The full-sync flag (libraryID == -1) is set at the end of a successful upgrade, so this
|
// The full-sync flag (libraryID == -1) is set at the end of a successful upgrade, so this
|
||||||
|
@ -120,6 +123,8 @@ Zotero.Sync.Data.Engine.prototype.start = Zotero.Promise.coroutine(function* ()
|
||||||
|
|
||||||
sync:
|
sync:
|
||||||
while (true) {
|
while (true) {
|
||||||
|
this._statusCheck();
|
||||||
|
|
||||||
let downloadResult, uploadResult;
|
let downloadResult, uploadResult;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -199,17 +204,11 @@ Zotero.Sync.Data.Engine.prototype.start = Zotero.Promise.coroutine(function* ()
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop all active requests
|
* Stop the sync process
|
||||||
*
|
|
||||||
* @return {Promise<PromiseInspection[]>} Promise from Zotero.Promise.settle()
|
|
||||||
*/
|
*/
|
||||||
Zotero.Sync.Data.Engine.prototype.stop = function () {
|
Zotero.Sync.Data.Engine.prototype.stop = function () {
|
||||||
var funcs;
|
Zotero.debug("Stopping sync for " + this.library.name);
|
||||||
var request;
|
this._stopping = true;
|
||||||
while (request = this.requests.shift()) {
|
|
||||||
funcs.push(() => request.stop());
|
|
||||||
}
|
|
||||||
return Zotero.Promise.settle(funcs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -254,7 +253,7 @@ Zotero.Sync.Data.Engine.prototype._startDownload = Zotero.Promise.coroutine(func
|
||||||
// Get other object types
|
// Get other object types
|
||||||
//
|
//
|
||||||
for (let objectType of Zotero.DataObjectUtilities.getTypesForLibrary(this.libraryID)) {
|
for (let objectType of Zotero.DataObjectUtilities.getTypesForLibrary(this.libraryID)) {
|
||||||
this._failedCheck();
|
this._statusCheck();
|
||||||
|
|
||||||
// For items, fetch top-level items first
|
// For items, fetch top-level items first
|
||||||
//
|
//
|
||||||
|
@ -496,7 +495,7 @@ Zotero.Sync.Data.Engine.prototype._downloadObjects = async function (objectType,
|
||||||
keys.forEach(key => objectData[key] = null);
|
keys.forEach(key => objectData[key] = null);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
this._failedCheck();
|
this._statusCheck();
|
||||||
|
|
||||||
// Get data we've downloaded in a previous loop but failed to process
|
// Get data we've downloaded in a previous loop but failed to process
|
||||||
var json = [];
|
var json = [];
|
||||||
|
@ -537,7 +536,7 @@ Zotero.Sync.Data.Engine.prototype._downloadObjects = async function (objectType,
|
||||||
await Zotero.Promise.map(
|
await Zotero.Promise.map(
|
||||||
json,
|
json,
|
||||||
async function (batch) {
|
async function (batch) {
|
||||||
this._failedCheck();
|
this._statusCheck();
|
||||||
|
|
||||||
Zotero.debug(`Processing batch of downloaded ${objectTypePlural} in ${this.library.name}`);
|
Zotero.debug(`Processing batch of downloaded ${objectTypePlural} in ${this.library.name}`);
|
||||||
|
|
||||||
|
@ -559,6 +558,10 @@ Zotero.Sync.Data.Engine.prototype._downloadObjects = async function (objectType,
|
||||||
this._getOptions({
|
this._getOptions({
|
||||||
onObjectProcessed: () => {
|
onObjectProcessed: () => {
|
||||||
num++;
|
num++;
|
||||||
|
// Check for stop every 5 items
|
||||||
|
if (num % 5 == 0) {
|
||||||
|
this._statusCheck();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// Increase the notifier batch size as we go, so that new items start coming in
|
// Increase the notifier batch size as we go, so that new items start coming in
|
||||||
// one by one but then switch to larger chunks
|
// one by one but then switch to larger chunks
|
||||||
|
@ -616,7 +619,7 @@ Zotero.Sync.Data.Engine.prototype._downloadObjects = async function (objectType,
|
||||||
await this._restoreRestoredCollectionItems(restored);
|
await this._restoreRestoredCollectionItems(restored);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._failedCheck();
|
this._statusCheck();
|
||||||
|
|
||||||
// If all requests were successful, such that we had a chance to see all keys, remove keys we
|
// If all requests were successful, such that we had a chance to see all keys, remove keys we
|
||||||
// didn't see from the sync queue so they don't keep being retried forever
|
// didn't see from the sync queue so they don't keep being retried forever
|
||||||
|
@ -665,6 +668,8 @@ Zotero.Sync.Data.Engine.prototype._downloadObjects = async function (objectType,
|
||||||
|
|
||||||
// Show conflict resolution window
|
// Show conflict resolution window
|
||||||
if (conflicts.length) {
|
if (conflicts.length) {
|
||||||
|
this._statusCheck();
|
||||||
|
|
||||||
let results = await Zotero.Sync.Data.Local.processConflicts(
|
let results = await Zotero.Sync.Data.Local.processConflicts(
|
||||||
objectType, this.libraryID, conflicts, this._getOptions()
|
objectType, this.libraryID, conflicts, this._getOptions()
|
||||||
);
|
);
|
||||||
|
@ -827,6 +832,8 @@ Zotero.Sync.Data.Engine.prototype._downloadDeletions = Zotero.Promise.coroutine(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conflicts.length) {
|
if (conflicts.length) {
|
||||||
|
this._statusCheck();
|
||||||
|
|
||||||
// Sort conflicts by Date Modified
|
// Sort conflicts by Date Modified
|
||||||
conflicts.sort(function (a, b) {
|
conflicts.sort(function (a, b) {
|
||||||
var d1 = a.left.dateModified;
|
var d1 = a.left.dateModified;
|
||||||
|
@ -936,6 +943,8 @@ Zotero.Sync.Data.Engine.prototype._startUpload = Zotero.Promise.coroutine(functi
|
||||||
|
|
||||||
// Get unsynced local objects for each object type
|
// Get unsynced local objects for each object type
|
||||||
for (let objectType of Zotero.DataObjectUtilities.getTypesForLibrary(this.libraryID)) {
|
for (let objectType of Zotero.DataObjectUtilities.getTypesForLibrary(this.libraryID)) {
|
||||||
|
this._statusCheck();
|
||||||
|
|
||||||
let objectTypePlural = Zotero.DataObjectUtilities.getObjectTypePlural(objectType);
|
let objectTypePlural = Zotero.DataObjectUtilities.getObjectTypePlural(objectType);
|
||||||
let objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(objectType);
|
let objectsClass = Zotero.DataObjectUtilities.getObjectsClassForObjectType(objectType);
|
||||||
|
|
||||||
|
@ -1015,6 +1024,8 @@ Zotero.Sync.Data.Engine.prototype._startUpload = Zotero.Promise.coroutine(functi
|
||||||
try {
|
try {
|
||||||
Zotero.debug(JSON.stringify(objectIDs));
|
Zotero.debug(JSON.stringify(objectIDs));
|
||||||
for (let objectType in objectIDs) {
|
for (let objectType in objectIDs) {
|
||||||
|
this._statusCheck();
|
||||||
|
|
||||||
libraryVersion = yield this._uploadObjects(
|
libraryVersion = yield this._uploadObjects(
|
||||||
objectType, objectIDs[objectType], libraryVersion
|
objectType, objectIDs[objectType], libraryVersion
|
||||||
);
|
);
|
||||||
|
@ -1022,6 +1033,8 @@ Zotero.Sync.Data.Engine.prototype._startUpload = Zotero.Promise.coroutine(functi
|
||||||
|
|
||||||
Zotero.debug(JSON.stringify(objectDeletions));
|
Zotero.debug(JSON.stringify(objectDeletions));
|
||||||
for (let objectType in objectDeletions) {
|
for (let objectType in objectDeletions) {
|
||||||
|
this._statusCheck();
|
||||||
|
|
||||||
libraryVersion = yield this._uploadDeletions(
|
libraryVersion = yield this._uploadDeletions(
|
||||||
objectType, objectDeletions[objectType], libraryVersion
|
objectType, objectDeletions[objectType], libraryVersion
|
||||||
);
|
);
|
||||||
|
@ -1562,7 +1575,7 @@ Zotero.Sync.Data.Engine.prototype._fullSync = Zotero.Promise.coroutine(function*
|
||||||
|
|
||||||
// Get object types
|
// Get object types
|
||||||
for (let objectType of Zotero.DataObjectUtilities.getTypesForLibrary(this.libraryID)) {
|
for (let objectType of Zotero.DataObjectUtilities.getTypesForLibrary(this.libraryID)) {
|
||||||
this._failedCheck();
|
this._statusCheck();
|
||||||
|
|
||||||
let objectTypePlural = Zotero.DataObjectUtilities.getObjectTypePlural(objectType);
|
let objectTypePlural = Zotero.DataObjectUtilities.getObjectTypePlural(objectType);
|
||||||
let ObjectType = Zotero.Utilities.capitalize(objectType);
|
let ObjectType = Zotero.Utilities.capitalize(objectType);
|
||||||
|
@ -1774,6 +1787,19 @@ Zotero.Sync.Data.Engine.prototype._checkObjectUploadError = Zotero.Promise.corou
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Zotero.Sync.Data.Engine.prototype._statusCheck = function () {
|
||||||
|
this._stopCheck();
|
||||||
|
this._failedCheck();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Zotero.Sync.Data.Engine.prototype._stopCheck = function () {
|
||||||
|
if (!this._stopping) return;
|
||||||
|
Zotero.debug("Sync stopped for " + this.library.name);
|
||||||
|
throw new Zotero.Sync.UserCancelledException;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Zotero.Sync.Data.Engine.prototype._failedCheck = function () {
|
Zotero.Sync.Data.Engine.prototype._failedCheck = function () {
|
||||||
if (this.stopOnError && this.failed) {
|
if (this.stopOnError && this.failed) {
|
||||||
Zotero.logError("Stopping on error");
|
Zotero.logError("Stopping on error");
|
||||||
|
|
|
@ -44,7 +44,7 @@ Zotero.Sync.Data.FullTextEngine = function (options) {
|
||||||
this.setStatus = options.setStatus || function () {};
|
this.setStatus = options.setStatus || function () {};
|
||||||
this.onError = options.onError || function (e) {};
|
this.onError = options.onError || function (e) {};
|
||||||
this.stopOnError = options.stopOnError;
|
this.stopOnError = options.stopOnError;
|
||||||
this.requestPromises = [];
|
this._stopping = false;
|
||||||
this.failed = false;
|
this.failed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,8 @@ Zotero.Sync.Data.FullTextEngine.prototype.start = Zotero.Promise.coroutine(funct
|
||||||
Zotero.debug("Library version hasn't changed -- skipping full-text download");
|
Zotero.debug("Library version hasn't changed -- skipping full-text download");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._stopCheck();
|
||||||
|
|
||||||
yield this._upload();
|
yield this._upload();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -95,22 +97,26 @@ Zotero.Sync.Data.FullTextEngine.prototype._download = Zotero.Promise.coroutine(f
|
||||||
}
|
}
|
||||||
|
|
||||||
this.requestPromises = [];
|
this.requestPromises = [];
|
||||||
for (let key of keys) {
|
|
||||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=449811
|
yield Zotero.Promise.map(
|
||||||
let tmpKey = key;
|
keys,
|
||||||
this.requestPromises.push(
|
(key) => {
|
||||||
|
this._stopCheck();
|
||||||
this.apiClient.getFullTextForItem(
|
this.apiClient.getFullTextForItem(
|
||||||
this.library.libraryType, this.library.libraryTypeID, key
|
this.library.libraryType, this.library.libraryTypeID, key
|
||||||
)
|
)
|
||||||
.then(function (results) {
|
.then((results) => {
|
||||||
|
this._stopCheck();
|
||||||
if (!results) return;
|
if (!results) return;
|
||||||
return Zotero.Fulltext.setItemContent(
|
return Zotero.Fulltext.setItemContent(
|
||||||
this.libraryID, tmpKey, results.data, results.version
|
this.libraryID, key, results.data, results.version
|
||||||
)
|
)
|
||||||
}.bind(this))
|
})
|
||||||
);
|
},
|
||||||
}
|
// Prepare twice the number of concurrent requests
|
||||||
yield Zotero.Promise.all(this.requestPromises);
|
{ concurrency: 8 }
|
||||||
|
);
|
||||||
|
|
||||||
yield Zotero.FullText.setLibraryVersion(this.libraryID, results.libraryVersion);
|
yield Zotero.FullText.setLibraryVersion(this.libraryID, results.libraryVersion);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -125,6 +131,8 @@ Zotero.Sync.Data.FullTextEngine.prototype._upload = Zotero.Promise.coroutine(fun
|
||||||
|
|
||||||
let lastItemID = 0;
|
let lastItemID = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
this._stopCheck();
|
||||||
|
|
||||||
let objs = yield Zotero.FullText.getUnsyncedContent(this.libraryID, {
|
let objs = yield Zotero.FullText.getUnsyncedContent(this.libraryID, {
|
||||||
maxSize: this.MAX_BATCH_SIZE,
|
maxSize: this.MAX_BATCH_SIZE,
|
||||||
maxItems: this.MAX_BATCH_ITEMS,
|
maxItems: this.MAX_BATCH_ITEMS,
|
||||||
|
@ -190,6 +198,13 @@ Zotero.Sync.Data.FullTextEngine.prototype._upload = Zotero.Promise.coroutine(fun
|
||||||
|
|
||||||
|
|
||||||
Zotero.Sync.Data.FullTextEngine.prototype.stop = Zotero.Promise.coroutine(function* () {
|
Zotero.Sync.Data.FullTextEngine.prototype.stop = Zotero.Promise.coroutine(function* () {
|
||||||
// TODO: Cancel requests
|
// TODO: Cancel requests?
|
||||||
throw new Error("Unimplemented");
|
this._stopping = true;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
Zotero.Sync.Data.FullTextEngine.prototype._stopCheck = function () {
|
||||||
|
if (!this._stopping) return;
|
||||||
|
Zotero.debug("Full-text sync stopped for " + this.library.name);
|
||||||
|
throw new Zotero.Sync.UserCancelledException;
|
||||||
|
}
|
||||||
|
|
|
@ -68,10 +68,10 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
var _autoSyncTimer;
|
var _autoSyncTimer;
|
||||||
var _firstInSession = true;
|
var _firstInSession = true;
|
||||||
var _syncInProgress = false;
|
var _syncInProgress = false;
|
||||||
|
var _stopping = false;
|
||||||
var _manualSyncRequired = false; // TODO: make public?
|
var _manualSyncRequired = false; // TODO: make public?
|
||||||
|
|
||||||
var _syncEngines = [];
|
var _currentEngine = null;
|
||||||
var _storageEngines = [];
|
|
||||||
var _storageControllers = {};
|
var _storageControllers = {};
|
||||||
|
|
||||||
var _lastSyncStatus;
|
var _lastSyncStatus;
|
||||||
|
@ -117,6 +117,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_syncInProgress = true;
|
_syncInProgress = true;
|
||||||
|
_stopping = false;
|
||||||
|
|
||||||
yield Zotero.Notifier.trigger('start', 'sync', []);
|
yield Zotero.Notifier.trigger('start', 'sync', []);
|
||||||
|
|
||||||
|
@ -139,9 +140,10 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
let client = this.getAPIClient({ apiKey });
|
let client = this.getAPIClient({ apiKey });
|
||||||
let keyInfo = yield this.checkAccess(client, options);
|
let keyInfo = yield this.checkAccess(client, options);
|
||||||
|
|
||||||
|
_stopCheck();
|
||||||
|
|
||||||
let emptyLibraryContinue = yield this.checkEmptyLibrary(keyInfo);
|
let emptyLibraryContinue = yield this.checkEmptyLibrary(keyInfo);
|
||||||
if (!emptyLibraryContinue) {
|
if (!emptyLibraryContinue) {
|
||||||
yield this.end(options);
|
|
||||||
Zotero.debug("Syncing cancelled because user library is empty");
|
Zotero.debug("Syncing cancelled because user library is empty");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -150,7 +152,6 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
.getService(Components.interfaces.nsIWindowMediator);
|
.getService(Components.interfaces.nsIWindowMediator);
|
||||||
let lastWin = wm.getMostRecentWindow("navigator:browser");
|
let lastWin = wm.getMostRecentWindow("navigator:browser");
|
||||||
if (!(yield Zotero.Sync.Data.Local.checkUser(lastWin, keyInfo.userID, keyInfo.username))) {
|
if (!(yield Zotero.Sync.Data.Local.checkUser(lastWin, keyInfo.userID, keyInfo.username))) {
|
||||||
yield this.end(options);
|
|
||||||
Zotero.debug("User cancelled sync on username mismatch");
|
Zotero.debug("User cancelled sync on username mismatch");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -179,6 +180,8 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
options.libraries ? Array.from(options.libraries) : []
|
options.libraries ? Array.from(options.libraries) : []
|
||||||
);
|
);
|
||||||
|
|
||||||
|
_stopCheck();
|
||||||
|
|
||||||
// If items not yet loaded for libraries we need, load them now
|
// If items not yet loaded for libraries we need, load them now
|
||||||
for (let libraryID of librariesToSync) {
|
for (let libraryID of librariesToSync) {
|
||||||
let library = Zotero.Libraries.get(libraryID);
|
let library = Zotero.Libraries.get(libraryID);
|
||||||
|
@ -187,10 +190,14 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_stopCheck();
|
||||||
|
|
||||||
// Sync data and files, and then repeat if necessary
|
// Sync data and files, and then repeat if necessary
|
||||||
let attempt = 1;
|
let attempt = 1;
|
||||||
let successfulLibraries = new Set(librariesToSync);
|
let successfulLibraries = new Set(librariesToSync);
|
||||||
while (librariesToSync.length) {
|
while (librariesToSync.length) {
|
||||||
|
_stopCheck();
|
||||||
|
|
||||||
if (attempt > 3) {
|
if (attempt > 3) {
|
||||||
// TODO: Back off and/or nicer error
|
// TODO: Back off and/or nicer error
|
||||||
throw new Error("Too many sync attempts -- stopping");
|
throw new Error("Too many sync attempts -- stopping");
|
||||||
|
@ -201,6 +208,8 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
successfulLibraries.delete(libraryID);
|
successfulLibraries.delete(libraryID);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_stopCheck();
|
||||||
|
|
||||||
// Run file sync on all libraries that passed the last data sync
|
// Run file sync on all libraries that passed the last data sync
|
||||||
librariesToSync = yield _doFileSync(nextLibraries, engineOptions);
|
librariesToSync = yield _doFileSync(nextLibraries, engineOptions);
|
||||||
if (librariesToSync.length) {
|
if (librariesToSync.length) {
|
||||||
|
@ -208,6 +217,8 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_stopCheck();
|
||||||
|
|
||||||
// Run full-text sync on all libraries that haven't failed a data sync
|
// Run full-text sync on all libraries that haven't failed a data sync
|
||||||
librariesToSync = yield _doFullTextSync([...successfulLibraries], engineOptions);
|
librariesToSync = yield _doFullTextSync([...successfulLibraries], engineOptions);
|
||||||
if (librariesToSync.length) {
|
if (librariesToSync.length) {
|
||||||
|
@ -550,13 +561,15 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
var _doDataSync = Zotero.Promise.coroutine(function* (libraries, options, skipUpdateLastSyncTime) {
|
var _doDataSync = Zotero.Promise.coroutine(function* (libraries, options, skipUpdateLastSyncTime) {
|
||||||
var successfulLibraries = [];
|
var successfulLibraries = [];
|
||||||
for (let libraryID of libraries) {
|
for (let libraryID of libraries) {
|
||||||
|
_stopCheck();
|
||||||
try {
|
try {
|
||||||
let opts = {};
|
let opts = {};
|
||||||
Object.assign(opts, options);
|
Object.assign(opts, options);
|
||||||
opts.libraryID = libraryID;
|
opts.libraryID = libraryID;
|
||||||
|
|
||||||
let engine = new Zotero.Sync.Data.Engine(opts);
|
_currentEngine = new Zotero.Sync.Data.Engine(opts);
|
||||||
yield engine.start();
|
yield _currentEngine.start();
|
||||||
|
_currentEngine = null;
|
||||||
successfulLibraries.push(libraryID);
|
successfulLibraries.push(libraryID);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
|
@ -597,6 +610,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
this.setSyncStatus(Zotero.getString('sync.status.syncingFiles'));
|
this.setSyncStatus(Zotero.getString('sync.status.syncingFiles'));
|
||||||
var resyncLibraries = []
|
var resyncLibraries = []
|
||||||
for (let libraryID of libraries) {
|
for (let libraryID of libraries) {
|
||||||
|
_stopCheck();
|
||||||
try {
|
try {
|
||||||
let opts = {};
|
let opts = {};
|
||||||
Object.assign(opts, options);
|
Object.assign(opts, options);
|
||||||
|
@ -611,8 +625,9 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
throw new Error("Too many file sync attempts for library " + libraryID);
|
throw new Error("Too many file sync attempts for library " + libraryID);
|
||||||
}
|
}
|
||||||
tries--;
|
tries--;
|
||||||
let engine = new Zotero.Sync.Storage.Engine(opts);
|
_currentEngine = new Zotero.Sync.Storage.Engine(opts);
|
||||||
let results = yield engine.start();
|
let results = yield _currentEngine.start();
|
||||||
|
_currentEngine = null;
|
||||||
if (results.syncRequired) {
|
if (results.syncRequired) {
|
||||||
resyncLibraries.push(libraryID);
|
resyncLibraries.push(libraryID);
|
||||||
}
|
}
|
||||||
|
@ -624,6 +639,15 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
|
if (e instanceof Zotero.Sync.UserCancelledException) {
|
||||||
|
if (e.advanceToNextLibrary) {
|
||||||
|
Zotero.debug("Storage sync cancelled for library " + libraryID + " -- "
|
||||||
|
+ "advancing to next library");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
Zotero.debug("File sync failed for library " + libraryID);
|
Zotero.debug("File sync failed for library " + libraryID);
|
||||||
Zotero.logError(e);
|
Zotero.logError(e);
|
||||||
this.checkError(e);
|
this.checkError(e);
|
||||||
|
@ -652,15 +676,21 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
this.setSyncStatus(Zotero.getString('sync.status.syncingFullText'));
|
this.setSyncStatus(Zotero.getString('sync.status.syncingFullText'));
|
||||||
var resyncLibraries = [];
|
var resyncLibraries = [];
|
||||||
for (let libraryID of libraries) {
|
for (let libraryID of libraries) {
|
||||||
|
_stopCheck();
|
||||||
try {
|
try {
|
||||||
let opts = {};
|
let opts = {};
|
||||||
Object.assign(opts, options);
|
Object.assign(opts, options);
|
||||||
opts.libraryID = libraryID;
|
opts.libraryID = libraryID;
|
||||||
|
|
||||||
let engine = new Zotero.Sync.Data.FullTextEngine(opts);
|
_currentEngine = new Zotero.Sync.Data.FullTextEngine(opts);
|
||||||
yield engine.start();
|
yield _currentEngine.start();
|
||||||
|
_currentEngine = null;
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
|
if (e instanceof Zotero.Sync.UserCancelledException) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
|
||||||
if (e instanceof Zotero.HTTP.UnexpectedStatusException && e.status == 412) {
|
if (e instanceof Zotero.HTTP.UnexpectedStatusException && e.status == 412) {
|
||||||
resyncLibraries.push(libraryID);
|
resyncLibraries.push(libraryID);
|
||||||
continue;
|
continue;
|
||||||
|
@ -762,8 +792,11 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
|
|
||||||
|
|
||||||
this.stop = function () {
|
this.stop = function () {
|
||||||
_syncEngines.forEach(engine => engine.stop());
|
this.setSyncStatus(Zotero.getString('sync.stopping'));
|
||||||
_storageEngines.forEach(engine => engine.stop());
|
_stopping = true;
|
||||||
|
if (_currentEngine) {
|
||||||
|
_currentEngine.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1143,14 +1176,17 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
|
|
||||||
// Update sync icon
|
// Update sync icon
|
||||||
var syncIcon = doc.getElementById('zotero-tb-sync');
|
var syncIcon = doc.getElementById('zotero-tb-sync');
|
||||||
|
var stopIcon = doc.getElementById('zotero-tb-sync-stop');
|
||||||
if (state == 'animate') {
|
if (state == 'animate') {
|
||||||
syncIcon.setAttribute('status', state);
|
syncIcon.setAttribute('status', state);
|
||||||
// Disable button while spinning
|
// Disable button while spinning
|
||||||
syncIcon.disabled = true;
|
syncIcon.disabled = true;
|
||||||
|
stopIcon.hidden = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
syncIcon.removeAttribute('status');
|
syncIcon.removeAttribute('status');
|
||||||
syncIcon.disabled = false;
|
syncIcon.disabled = false;
|
||||||
|
stopIcon.hidden = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1386,4 +1422,11 @@ Zotero.Sync.Runner_Module = function (options = {}) {
|
||||||
// Set as .apiKey on Runner in tests or set in login manager
|
// Set as .apiKey on Runner in tests or set in login manager
|
||||||
return _apiKey || Zotero.Sync.Data.Local.getAPIKey()
|
return _apiKey || Zotero.Sync.Data.Local.getAPIKey()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
function _stopCheck() {
|
||||||
|
if (_stopping) {
|
||||||
|
throw new Zotero.Sync.UserCancelledException;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -210,6 +210,10 @@
|
||||||
</toolbarbutton>
|
</toolbarbutton>
|
||||||
</hbox>
|
</hbox>
|
||||||
<hbox align="center" pack="end">
|
<hbox align="center" pack="end">
|
||||||
|
<toolbarbutton id="zotero-tb-sync-stop"
|
||||||
|
tooltiptext="&zotero.sync.stop;"
|
||||||
|
oncommand="this.hidden = true; Zotero.Sync.Runner.stop()"
|
||||||
|
hidden="true"/>
|
||||||
<hbox id="zotero-tb-sync-progress-box" hidden="true" align="center">
|
<hbox id="zotero-tb-sync-progress-box" hidden="true" align="center">
|
||||||
<!-- TODO: localize -->
|
<!-- TODO: localize -->
|
||||||
<toolbarbutton id="zotero-tb-sync-storage-cancel"
|
<toolbarbutton id="zotero-tb-sync-storage-cancel"
|
||||||
|
|
|
@ -237,6 +237,7 @@
|
||||||
|
|
||||||
<!ENTITY zotero.integration.references.label "References in Bibliography">
|
<!ENTITY zotero.integration.references.label "References in Bibliography">
|
||||||
|
|
||||||
|
<!ENTITY zotero.sync.stop "Stop Sync">
|
||||||
<!ENTITY zotero.sync.error "Sync Error">
|
<!ENTITY zotero.sync.error "Sync Error">
|
||||||
<!ENTITY zotero.sync.storage.progress "Progress:">
|
<!ENTITY zotero.sync.storage.progress "Progress:">
|
||||||
<!ENTITY zotero.sync.storage.downloads "Downloads:">
|
<!ENTITY zotero.sync.storage.downloads "Downloads:">
|
||||||
|
|
|
@ -865,6 +865,7 @@ styles.abbreviations.missingInfo = The abbreviations file "%1$S" does not specif
|
||||||
|
|
||||||
sync.sync = Sync
|
sync.sync = Sync
|
||||||
sync.syncWith = Sync with %S
|
sync.syncWith = Sync with %S
|
||||||
|
sync.stopping = Stopping…
|
||||||
sync.cancel = Cancel Sync
|
sync.cancel = Cancel Sync
|
||||||
sync.openSyncPreferences = Open Sync Preferences
|
sync.openSyncPreferences = Open Sync Preferences
|
||||||
sync.resetGroupAndSync = Reset Group and Sync
|
sync.resetGroupAndSync = Reset Group and Sync
|
||||||
|
|
|
@ -555,7 +555,7 @@
|
||||||
list-style-image: url('chrome://zotero/skin/toolbar-go-arrow.png');
|
list-style-image: url('chrome://zotero/skin/toolbar-go-arrow.png');
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-tb-sync-storage-cancel
|
#zotero-tb-sync-stop
|
||||||
{
|
{
|
||||||
list-style-image: url(chrome://zotero/skin/control_stop_blue.png);
|
list-style-image: url(chrome://zotero/skin/control_stop_blue.png);
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
|
@ -745,7 +745,7 @@
|
||||||
.zotero-menuitem-create-report { list-style-image: url('chrome://zotero/skin/treeitem-report@2x.png'); }
|
.zotero-menuitem-create-report { list-style-image: url('chrome://zotero/skin/treeitem-report@2x.png'); }
|
||||||
#zotero-tb-advanced-search { list-style-image: url('chrome://zotero/skin/toolbar-advanced-search@2x.png'); }
|
#zotero-tb-advanced-search { list-style-image: url('chrome://zotero/skin/toolbar-advanced-search@2x.png'); }
|
||||||
#zotero-tb-locate { list-style-image: url('chrome://zotero/skin/toolbar-go-arrow@2x.png'); }
|
#zotero-tb-locate { list-style-image: url('chrome://zotero/skin/toolbar-go-arrow@2x.png'); }
|
||||||
#zotero-tb-sync-storage-cancel { list-style-image: url(chrome://zotero/skin/control_stop_blue@2x.png); margin-right: 0; }
|
#zotero-tb-sync-stop { list-style-image: url(chrome://zotero/skin/control_stop_blue@2x.png); margin-right: 0; }
|
||||||
#zotero-tb-sync-error { list-style-image: url(chrome://zotero/skin/error@2x.png); }
|
#zotero-tb-sync-error { list-style-image: url(chrome://zotero/skin/error@2x.png); }
|
||||||
#zotero-tb-sync-error[state=warning] { list-style-image: url(chrome://zotero/skin/warning@2x.png); }
|
#zotero-tb-sync-error[state=warning] { list-style-image: url(chrome://zotero/skin/warning@2x.png); }
|
||||||
#zotero-pane-stack[fullscreenmode="true"] #zotero-tb-fullscreen { list-style-image: url('chrome://zotero/skin/toolbar-fullscreen-top@2x.png'); }
|
#zotero-pane-stack[fullscreenmode="true"] #zotero-tb-fullscreen { list-style-image: url('chrome://zotero/skin/toolbar-fullscreen-top@2x.png'); }
|
||||||
|
|
Loading…
Add table
Reference in a new issue