commit e1cc377162144e129f948092a529db3218d4824d
parent 15c79766e86e92b7d94f1771459c9aaad8d40c7a
Author: Dan Stillman <dstillman@zotero.org>
Date: Wed, 21 Sep 2011 23:00:20 +0000
Show Zotero pane progress bar during sync processing
TODO: limit to large syncs?
This needs a lot of testing.
Also:
- Tweak pumpGenerator() wait level behavior to match Zotero.wait()
- If Zotero is closed in the top-most window, show a popup instead of the pane-covering progress meter, and take an optional icon in Zotero.showZoteroPaneProgressMeter() for use in the popup
- Restore protection against opening Zotero pane when Zotero.locked is set
- Display a nicer error if Zotero.DB.commitTransaction() is called without an active transaction
- Allow text with icons to extend to multiple lines in progressWindow popup
- Automatically use current window if one isn't specified in Zotero.repaint()
Diffstat:
9 files changed, 342 insertions(+), 218 deletions(-)
diff --git a/chrome/content/zotero/browser.js b/chrome/content/zotero/browser.js
@@ -136,7 +136,6 @@ var Zotero_Browser = new function() {
Zotero_Browser.progress.show();
Zotero_Browser.progress.startCloseTimer(8000);
return;
- return;
}
if (!Zotero.stateCheck()) {
diff --git a/chrome/content/zotero/overlay.js b/chrome/content/zotero/overlay.js
@@ -198,10 +198,6 @@ var ZoteroOverlay = new function()
if(makeVisible === undefined) makeVisible = zoteroPane.hidden || zoteroPane.collapsed;
- zoteroSplitter.setAttribute('hidden', !makeVisible);
- zoteroPane.setAttribute('hidden', false);
- zoteroPane.setAttribute('collapsed', false);
-
/*
Zotero.debug("zoteroPane.boxObject.height: " + zoteroPane.boxObject.height);
Zotero.debug("zoteroPane.getAttribute('height'): " + zoteroPane.getAttribute('height'));
@@ -210,6 +206,18 @@ var ZoteroOverlay = new function()
*/
if(makeVisible) {
+ if (Zotero.locked) {
+ var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
+ .getService(Components.interfaces.nsIPromptService);
+ var msg = Zotero.getString('general.operationInProgress') + '\n\n' + Zotero.getString('general.operationInProgress.waitUntilFinished');
+ ps.alert(null, "", msg);
+ return false;
+ }
+
+ zoteroSplitter.setAttribute('hidden', false);
+ zoteroPane.setAttribute('hidden', false);
+ zoteroPane.setAttribute('collapsed', false);
+
// Get saved height (makeVisible() may change it)
if (zoteroPane.hasAttribute('savedHeight')) {
var savedHeight = zoteroPane.getAttribute('savedHeight');
@@ -232,6 +240,7 @@ var ZoteroOverlay = new function()
ZoteroPane.makeHidden();
// Collapse pane
+ zoteroSplitter.setAttribute('hidden', true);
zoteroPane.setAttribute('collapsed', true);
zoteroPane.height = 0;
diff --git a/chrome/content/zotero/progressWindow.xul b/chrome/content/zotero/progressWindow.xul
@@ -9,7 +9,7 @@
<hbox id="zotero-progress-box">
<vbox id="zotero-progress-text-box">
- <label id="zotero-progress-text-headline" style="font-weight: bold;" />
+ <label id="zotero-progress-text-headline"/>
</vbox>
</hbox>
</window>
diff --git a/chrome/content/zotero/xpcom/db.js b/chrome/content/zotero/xpcom/db.js
@@ -484,6 +484,10 @@ Zotero.DBConnection.prototype.commitTransaction = function () {
}
try {
+ if (!db.transactionInProgress) {
+ throw new Error("No transaction in progress");
+ }
+
db.commitTransaction();
if (this.transactionVacuum) {
diff --git a/chrome/content/zotero/xpcom/progressWindow.js b/chrome/content/zotero/xpcom/progressWindow.js
@@ -172,31 +172,38 @@ Zotero.ProgressWindow = function(_window){
}
}
- function addLines(label, icon) {
+ function addLines(labels, icons) {
if(_windowLoaded) {
- for (var i in label) {
- var newLabel = _progressWindow.document.createElement("label");
- newLabel.setAttribute("class", "zotero-progress-item-label");
- newLabel.setAttribute("crop", "end");
- newLabel.setAttribute("value", label[i]);
+ for (var i in labels) {
+ var newText = _progressWindow.document.createElement("description");
+ newText.appendChild(
+ _progressWindow.document.createTextNode(labels[i])
+ );
+ newText.setAttribute("class", "zotero-progress-item-label");
+ newText.setAttribute("crop", "end");
+ var newImageHolder = _progressWindow.document.createElement("vbox");
var newImage = _progressWindow.document.createElement("image");
newImage.setAttribute("class", "zotero-progress-item-icon");
- newImage.setAttribute("src", icon[i]);
+ newImage.setAttribute("src", icons[i]);
+ newImage.setAttribute("flex", 0);
+ newImage.setAttribute("orient", "horizontal");
+ newImage.setAttribute("pack", "start");
+ newImageHolder.appendChild(newImage);
var newHB = _progressWindow.document.createElement("hbox");
newHB.setAttribute("class", "zotero-progress-item-hbox");
- newHB.setAttribute("valign", "center");
- newHB.appendChild(newImage);
- newHB.appendChild(newLabel);
+
+ newHB.appendChild(newImageHolder);
+ newHB.appendChild(newText);
_progressWindow.document.getElementById("zotero-progress-text-box").appendChild(newHB);
}
_move();
} else {
- _loadLines = _loadLines.concat(label);
- _loadIcons = _loadIcons.concat(icon);
+ _loadLines = _loadLines.concat(labels);
+ _loadIcons = _loadIcons.concat(icons);
}
}
diff --git a/chrome/content/zotero/xpcom/sync.js b/chrome/content/zotero/xpcom/sync.js
@@ -1451,196 +1451,229 @@ Zotero.Sync.Server = new function () {
Zotero.suppressUIUpdates = true;
_updatesInProgress = true;
- try {
- var xmlstr = Zotero.Sync.Server.Data.processUpdatedXML(
- xml.updated, lastLocalSyncDate, syncSession, libraryID
+ var progressMeter = true;
+ if (progressMeter) {
+ Zotero.showZoteroPaneProgressMeter(
+ Zotero.getString('sync.status.processingUpdatedData'),
+ false,
+ "chrome://zotero/skin/arrow_rotate_animated.png"
);
}
- finally {
- Zotero.suppressUIUpdates = false;
- _updatesInProgress = false;
- }
-
- //Zotero.debug(xmlstr);
- //throw('break');
-
- if (xmlstr === false) {
- Zotero.debug("Sync cancelled");
- Zotero.DB.rollbackTransaction();
- Zotero.reloadDataObjects();
- Zotero.Sync.EventListener.resetIgnored();
- _syncInProgress = false;
- _callbacks.onStop();
- return;
- }
-
- if (xmlstr) {
- Zotero.debug(xmlstr);
- }
- if (!xmlstr) {
- Zotero.debug("Nothing to upload to server");
- Zotero.Sync.Server.lastRemoteSyncTime = response.getAttribute('timestamp');
- Zotero.Sync.Server.lastLocalSyncTime = nextLocalSyncTime;
- Zotero.Sync.Server.nextLocalSyncDate = false;
- Zotero.DB.commitTransaction();
- _syncInProgress = false;
- _callbacks.onSuccess();
- return;
- }
-
- Zotero.DB.commitTransaction();
-
- Zotero.Sync.Runner.setSyncStatus(Zotero.getString('sync.status.uploadingData'));
-
- var url = _serverURL + 'upload';
- var body = _apiVersionComponent
- + '&' + Zotero.Sync.Server.sessionIDComponent
- + '&updateKey=' + updateKey
- + '&data=' + encodeURIComponent(xmlstr);
-
- //var file = Zotero.getZoteroDirectory();
- //file.append('lastupload.txt');
- //Zotero.File.putContents(file, body);
-
- var uploadCallback = function (xmlhttp) {
- if (xmlhttp.status == 409) {
- Zotero.debug("Upload key is no longer valid -- restarting sync");
- setTimeout(function () {
- Zotero.Sync.Server.sync(_callbacks, true, true);
- }, 1);
- return;
- }
-
- _checkResponse(xmlhttp);
-
- Zotero.debug(xmlhttp.responseText);
- var response = xmlhttp.responseXML.childNodes[0];
-
- if (_checkServerLock(response, function (mode) {
- switch (mode) {
- // If the upload was queued, keep checking back
- case 'queued':
- Zotero.Sync.Runner.setSyncStatus(Zotero.getString('sync.status.uploadAccepted'));
+ try {
+ var gen = Zotero.Sync.Server.Data.processUpdatedXML(
+ xml.updated, lastLocalSyncDate, syncSession, libraryID, function (xmlstr) {
+ try {
+ Zotero.UnresponsiveScriptIndicator.enable();
+
+ if (progressMeter) {
+ Zotero.hideZoteroPaneOverlay();
+ }
+ Zotero.suppressUIUpdates = false;
+ _updatesInProgress = false;
+
+ //Zotero.debug(xmlstr);
+ //throw('break');
+
+ if (xmlstr === false) {
+ Zotero.debug("Sync cancelled");
+ Zotero.DB.rollbackTransaction();
+ Zotero.reloadDataObjects();
+ Zotero.Sync.EventListener.resetIgnored();
+ _syncInProgress = false;
+ _callbacks.onStop();
+ return;
+ }
+
+ if (xmlstr) {
+ Zotero.debug(xmlstr);
+ }
+
+ if (!xmlstr) {
+ Zotero.debug("Nothing to upload to server");
+ Zotero.Sync.Server.lastRemoteSyncTime = response.getAttribute('timestamp');
+ Zotero.Sync.Server.lastLocalSyncTime = nextLocalSyncTime;
+ Zotero.Sync.Server.nextLocalSyncDate = false;
+ Zotero.DB.commitTransaction();
+ _syncInProgress = false;
+ _callbacks.onSuccess();
+ return;
+ }
+
+ Zotero.DB.commitTransaction();
+
+ Zotero.Sync.Runner.setSyncStatus(Zotero.getString('sync.status.uploadingData'));
- var url = _serverURL + 'uploadstatus';
+ var url = _serverURL + 'upload';
var body = _apiVersionComponent
- + '&' + Zotero.Sync.Server.sessionIDComponent;
- Zotero.HTTP.doPost(url, body, function (xmlhttp) {
- uploadCallback(xmlhttp);
- });
- break;
-
- // If affected libraries were locked, restart sync,
- // since the upload key would be out of date anyway
- case 'locked':
- setTimeout(function () {
- Zotero.Sync.Server.sync(_callbacks, true, true);
- }, 1);
- break;
+ + '&' + Zotero.Sync.Server.sessionIDComponent
+ + '&updateKey=' + updateKey
+ + '&data=' + encodeURIComponent(xmlstr);
- default:
- throw ("Unexpected server lock mode '" + mode + "' in Zotero.Sync.Server.upload()");
- }
- })) { return; }
-
- if (response.firstChild.tagName == 'error') {
- // handle error
- _error(response.firstChild.firstChild.nodeValue);
- }
-
- if (response.firstChild.localName != 'uploaded') {
- _error("Unexpected upload response '" + response.firstChild.localName
- + "' in Zotero.Sync.Server.sync()");
- }
-
- Zotero.DB.beginTransaction();
- Zotero.Sync.purgeDeletedObjects(nextLocalSyncTime);
- Zotero.Sync.Server.lastLocalSyncTime = nextLocalSyncTime;
- Zotero.Sync.Server.nextLocalSyncDate = false;
- Zotero.Sync.Server.lastRemoteSyncTime = response.getAttribute('timestamp');
-
- //throw('break2');
-
- Zotero.DB.commitTransaction();
-
- // Check if any items were modified during /upload,
- // and restart the sync if so
- if (Zotero.Items.getNewer(nextLocalSyncDate, true)) {
- Zotero.debug("Items were modified during upload -- restarting sync");
- Zotero.Sync.Server.sync(_callbacks, true, true);
- return;
- }
-
- _syncInProgress = false;
- _callbacks.onSuccess();
- }
-
- var compress = Zotero.Prefs.get('sync.server.compressData');
- // Compress upload data
- if (compress) {
- // Callback when compressed data is available
- var bufferUploader = function (data) {
- var gzurl = url + '?gzip=1';
-
- var oldLen = body.length;
- var newLen = data.length;
- var savings = Math.round(((oldLen - newLen) / oldLen) * 100)
- Zotero.debug("HTTP POST " + newLen + " bytes to " + gzurl
- + " (gzipped from " + oldLen + " bytes; "
- + savings + "% savings)");
-
- if (Zotero.HTTP.browserIsOffline()) {
- Zotero.debug('Browser is offline');
- return false;
- }
-
- var req =
- Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].
- createInstance();
- req.open('POST', gzurl, true);
- req.setRequestHeader('Content-Type', "application/octet-stream");
- req.setRequestHeader('Content-Encoding', 'gzip');
-
- req.onreadystatechange = function () {
- if (req.readyState == 4) {
- uploadCallback(req);
+ //var file = Zotero.getZoteroDirectory();
+ //file.append('lastupload.txt');
+ //Zotero.File.putContents(file, body);
+
+ var uploadCallback = function (xmlhttp) {
+ if (xmlhttp.status == 409) {
+ Zotero.debug("Upload key is no longer valid -- restarting sync");
+ setTimeout(function () {
+ Zotero.Sync.Server.sync(_callbacks, true, true);
+ }, 1);
+ return;
+ }
+
+ _checkResponse(xmlhttp);
+
+ Zotero.debug(xmlhttp.responseText);
+ var response = xmlhttp.responseXML.childNodes[0];
+
+ if (_checkServerLock(response, function (mode) {
+ switch (mode) {
+ // If the upload was queued, keep checking back
+ case 'queued':
+ Zotero.Sync.Runner.setSyncStatus(Zotero.getString('sync.status.uploadAccepted'));
+
+ var url = _serverURL + 'uploadstatus';
+ var body = _apiVersionComponent
+ + '&' + Zotero.Sync.Server.sessionIDComponent;
+ Zotero.HTTP.doPost(url, body, function (xmlhttp) {
+ uploadCallback(xmlhttp);
+ });
+ break;
+
+ // If affected libraries were locked, restart sync,
+ // since the upload key would be out of date anyway
+ case 'locked':
+ setTimeout(function () {
+ Zotero.Sync.Server.sync(_callbacks, true, true);
+ }, 1);
+ break;
+
+ default:
+ throw ("Unexpected server lock mode '" + mode + "' in Zotero.Sync.Server.upload()");
+ }
+ })) { return; }
+
+ if (response.firstChild.tagName == 'error') {
+ // handle error
+ _error(response.firstChild.firstChild.nodeValue);
+ }
+
+ if (response.firstChild.localName != 'uploaded') {
+ _error("Unexpected upload response '" + response.firstChild.localName
+ + "' in Zotero.Sync.Server.sync()");
+ }
+
+ Zotero.DB.beginTransaction();
+ Zotero.Sync.purgeDeletedObjects(nextLocalSyncTime);
+ Zotero.Sync.Server.lastLocalSyncTime = nextLocalSyncTime;
+ Zotero.Sync.Server.nextLocalSyncDate = false;
+ Zotero.Sync.Server.lastRemoteSyncTime = response.getAttribute('timestamp');
+
+ //throw('break2');
+
+ Zotero.DB.commitTransaction();
+
+ // Check if any items were modified during /upload,
+ // and restart the sync if so
+ if (Zotero.Items.getNewer(nextLocalSyncDate, true)) {
+ Zotero.debug("Items were modified during upload -- restarting sync");
+ Zotero.Sync.Server.sync(_callbacks, true, true);
+ return;
+ }
+
+ _syncInProgress = false;
+ _callbacks.onSuccess();
+ }
+
+ var compress = Zotero.Prefs.get('sync.server.compressData');
+ // Compress upload data
+ if (compress) {
+ // Callback when compressed data is available
+ var bufferUploader = function (data) {
+ var gzurl = url + '?gzip=1';
+
+ var oldLen = body.length;
+ var newLen = data.length;
+ var savings = Math.round(((oldLen - newLen) / oldLen) * 100)
+ Zotero.debug("HTTP POST " + newLen + " bytes to " + gzurl
+ + " (gzipped from " + oldLen + " bytes; "
+ + savings + "% savings)");
+
+ if (Zotero.HTTP.browserIsOffline()) {
+ Zotero.debug('Browser is offline');
+ return false;
+ }
+
+ var req =
+ Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"].
+ createInstance();
+ req.open('POST', gzurl, true);
+ req.setRequestHeader('Content-Type', "application/octet-stream");
+ req.setRequestHeader('Content-Encoding', 'gzip');
+
+ req.onreadystatechange = function () {
+ if (req.readyState == 4) {
+ uploadCallback(req);
+ }
+ };
+ try {
+ req.sendAsBinary(data);
+ }
+ catch (e) {
+ _error(e);
+ }
+ }
+
+ // Get input stream from POST data
+ var unicodeConverter =
+ Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
+ .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
+ unicodeConverter.charset = "UTF-8";
+ var bodyStream = unicodeConverter.convertToInputStream(body);
+
+ // Get listener for when compression is done
+ var listener = new Zotero.BufferedInputListener(bufferUploader);
+
+ // Initialize stream converter
+ var converter =
+ Components.classes["@mozilla.org/streamconv;1?from=uncompressed&to=gzip"]
+ .createInstance(Components.interfaces.nsIStreamConverter);
+ converter.asyncConvertData("uncompressed", "gzip", listener, null);
+
+ // Send input stream to stream converter
+ var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].
+ createInstance(Components.interfaces.nsIInputStreamPump);
+ pump.init(bodyStream, -1, -1, 0, 0, true);
+ pump.asyncRead(converter, null);
+ }
+
+ // Don't compress upload data
+ else {
+ Zotero.HTTP.doPost(url, body, uploadCallback);
+ }
+ }
+ catch (e) {
+ _error(e);
}
- };
- try {
- req.sendAsBinary(data);
- }
- catch (e) {
- _error(e);
}
- }
+ );
- // Get input stream from POST data
- var unicodeConverter =
- Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
- .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
- unicodeConverter.charset = "UTF-8";
- var bodyStream = unicodeConverter.convertToInputStream(body);
+ Zotero.pumpGenerator(gen);
+ }
+ catch (e) {
+ Zotero.DB.rollbackTransaction();
- // Get listener for when compression is done
- var listener = new Zotero.BufferedInputListener(bufferUploader);
+ Zotero.UnresponsiveScriptIndicator.enable();
- // Initialize stream converter
- var converter =
- Components.classes["@mozilla.org/streamconv;1?from=uncompressed&to=gzip"]
- .createInstance(Components.interfaces.nsIStreamConverter);
- converter.asyncConvertData("uncompressed", "gzip", listener, null);
+ if (progressMeter) {
+ Zotero.hideZoteroPaneOverlay();
+ }
+ Zotero.suppressUIUpdates = false;
+ _updatesInProgress = false;
- // Send input stream to stream converter
- var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].
- createInstance(Components.interfaces.nsIInputStreamPump);
- pump.init(bodyStream, -1, -1, 0, 0, true);
- pump.asyncRead(converter, null);
- }
-
- // Don't compress upload data
- else {
- Zotero.HTTP.doPost(url, body, uploadCallback);
+ throw (e);
}
}
catch (e) {
@@ -2410,7 +2443,7 @@ Zotero.Sync.Server.Session.prototype._addToKeySet = function (keySet, objs) {
key: obj.key
});
}
- Zotero.debug('a');
+
this.uploadKeys[keySet].addLibraryKeyPairs(type, keyPairs)
}
@@ -2475,17 +2508,29 @@ Zotero.Sync.Server.Data = new function() {
}
- function processUpdatedXML(xml, lastLocalSyncDate, syncSession, defaultLibraryID) {
+ function processUpdatedXML(xml, lastLocalSyncDate, syncSession, defaultLibraryID, callback) {
if (xml.children().length() == 0) {
Zotero.debug('No changes received from server');
- return Zotero.Sync.Server.Data.buildUploadXML(syncSession);
+ callback(Zotero.Sync.Server.Data.buildUploadXML(syncSession));
+ return;
}
function _libID(libraryID) {
return _getLibraryID(libraryID, defaultLibraryID);
}
- Zotero.DB.beginTransaction();
+ function _timeToYield() {
+ if (progressMeter && Date.now() - lastRepaint > repaintTime) {
+ lastRepaint = Date.now();
+ return true;
+ }
+
+ return false;
+ }
+
+ var progressMeter = Zotero.locked;
+ var repaintTime = 100;
+ var lastRepaint = Date.now();
var deletedCollectionKeys = _getDeletedCollectionKeys(xml);
@@ -2503,6 +2548,8 @@ Zotero.Sync.Server.Data = new function() {
}
}
+ if (_timeToYield()) yield true;
+
// Remotely deleted groups
if (xml.deleted.groups.toString()) {
Zotero.debug("Processing remotely deleted groups");
@@ -2521,6 +2568,8 @@ Zotero.Sync.Server.Data = new function() {
}
}
+ if (_timeToYield()) yield true;
+
// Get unmodified creators embedded within items -- this is necessary if, say,
// a creator was deleted locally and appears in a new/modified item remotely
var embeddedCreators = {};
@@ -2574,6 +2623,8 @@ Zotero.Sync.Server.Data = new function() {
}
}
+ if (_timeToYield()) yield true;
+
// Other objects
for each(var syncObject in Zotero.Sync.syncObjects) {
var Type = syncObject.singular; // 'Item'
@@ -2842,7 +2893,6 @@ Zotero.Sync.Server.Data = new function() {
}
if (mod) {
obj.dateModified = Zotero.DB.transactionDateTime;
- Zotero.debug('d');
syncSession.addToUpdated({
objectType: 'tag',
libraryID: obj.libraryID,
@@ -2951,9 +3001,10 @@ Zotero.Sync.Server.Data = new function() {
syncSession.addToUpdated(obj);
}
}
+
+ if (_timeToYield()) yield true;
}
-
//
// Handle remotely deleted objects
//
@@ -3015,6 +3066,8 @@ Zotero.Sync.Server.Data = new function() {
throw ('Delete reconciliation unimplemented for ' + types);
}
}
+
+ if (_timeToYield()) yield true;
}
@@ -3036,7 +3089,8 @@ Zotero.Sync.Server.Data = new function() {
var mergeData = _reconcile(type, toReconcile, remoteCreatorStore);
if (!mergeData) {
Zotero.DB.rollbackTransaction();
- return false;
+ callback(false);
+ return;
}
_processMergeData(
syncSession,
@@ -3048,6 +3102,8 @@ Zotero.Sync.Server.Data = new function() {
);
}
+ if (_timeToYield()) yield true;
+
// Save objects
Zotero.debug('Saving merged ' + types);
@@ -3085,6 +3141,8 @@ Zotero.Sync.Server.Data = new function() {
if (store) {
childItemStore.push(obj.id)
}
+
+ if (_timeToYield()) yield true;
}
// Add back related items (which now exist)
@@ -3118,6 +3176,8 @@ Zotero.Sync.Server.Data = new function() {
// rename the tag, add a new one with the old name, and sync.
for each(var obj in toSave) {
obj.save(true);
+
+ if (_timeToYield()) yield true;
}
}
else if (type == 'relation') {
@@ -3126,11 +3186,15 @@ Zotero.Sync.Server.Data = new function() {
continue;
}
obj.save();
+
+ if (_timeToYield()) yield true;
}
}
else {
for each(var obj in toSave) {
obj.save();
+
+ if (_timeToYield()) yield true;
}
}
@@ -3149,6 +3213,8 @@ Zotero.Sync.Server.Data = new function() {
else {
parents.push(item.id);
}
+
+ if (_timeToYield()) yield true;
}
// Lock dateModified in local versions of remotely deleted
@@ -3186,6 +3252,8 @@ Zotero.Sync.Server.Data = new function() {
}
}
+ if (_timeToYield()) yield true;
+
// Check mod times and hashes of updated items against stored values to see
// if they've been updated elsewhere and mark for download if so
if (type == 'item') {
@@ -3203,16 +3271,17 @@ Zotero.Sync.Server.Data = new function() {
}
}
+ if (_timeToYield()) yield true;
+
var xmlstr = Zotero.Sync.Server.Data.buildUploadXML(syncSession);
if (Zotero.Prefs.get('sync.debugBreak')) {
Zotero.debug(xmlstr);
- throw ('break');
+ callback(false);
+ return;
}
- Zotero.DB.commitTransaction();
-
- return xmlstr;
+ callback(xmlstr);
}
diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js
@@ -179,6 +179,7 @@ if(appInfo.platformVersion[0] >= 2) {
var _unlockCallbacks = [];
var _shutdownListeners = [];
var _progressMeters;
+ var _progressPopup;
var _lastPercentage;
// whether we are waiting for another Zotero process to release its DB lock
@@ -1472,6 +1473,12 @@ if(appInfo.platformVersion[0] >= 2) {
this.repaint = function(window, force) {
var now = Date.now();
+ if (!window) {
+ window = Components.classes["@mozilla.org/appshell/window-mediator;1"]
+ .getService(Components.interfaces.nsIWindowMediator)
+ .getMostRecentWindow("navigator:browser");
+ }
+
// Don't repaint more than 10 times per second unless forced.
if(!force && window.zoteroLastRepaint && (now - window.zoteroLastRepaint) < 100) return
@@ -1503,8 +1510,12 @@ if(appInfo.platformVersion[0] >= 2) {
createInstance(Components.interfaces.nsITimer);
var timerCallback = {"notify":function() {
var err = false;
+ _waiting--;
try {
- if(generator.next()) return;
+ if(generator.next()) {
+ _waiting++;
+ return;
+ }
} catch(e if e.toString() === "[object StopIteration]") {
// There must be a better way to perform this check
} catch(e) {
@@ -1513,7 +1524,6 @@ if(appInfo.platformVersion[0] >= 2) {
timer.cancel();
_runningTimers.splice(_runningTimers.indexOf(timer), 1);
- _waiting--;
if(err) throw err;
}}
@@ -1559,17 +1569,32 @@ if(appInfo.platformVersion[0] >= 2) {
* @param {Boolean} [determinate=false]
* @return void
*/
- this.showZoteroPaneProgressMeter = function (msg, determinate) {
- Zotero.debug("showing progress meter");
+ this.showZoteroPaneProgressMeter = function (msg, determinate, icon) {
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
+ var currentWindow = wm.getMostRecentWindow("navigator:browser");
var enumerator = wm.getEnumerator("navigator:browser");
var progressMeters = [];
while (enumerator.hasMoreElements()) {
var win = enumerator.getNext();
- Zotero.debug("win found");
if(!win.ZoteroPane) continue;
- Zotero.debug("win has pane");
+ if(!win.ZoteroPane.isShowing()) {
+ if (win != currentWindow) {
+ continue;
+ }
+
+ // If Zotero is closed in the top-most window, show a popup instead
+ _progressPopup = new Zotero.ProgressWindow();
+ _progressPopup.changeHeadline("Zotero");
+ if (icon) {
+ _progressPopup.addLines([msg], [icon]);
+ }
+ else {
+ _progressPopup.addDescription(msg);
+ }
+ _progressPopup.show();
+ continue;
+ }
win.ZoteroPane.document.getElementById('zotero-pane-progress-label').value = msg;
var progressMeter = win.ZoteroPane.document.getElementById('zotero-pane-progressmeter')
@@ -1586,7 +1611,6 @@ if(appInfo.platformVersion[0] >= 2) {
win.ZoteroPane.document.getElementById('zotero-pane-overlay-deck').selectedIndex = 0;
progressMeters.push(progressMeter);
- Zotero.debug("added meter for win");
}
_locked = true;
_progressMeters = progressMeters;
@@ -1643,8 +1667,14 @@ if(appInfo.platformVersion[0] >= 2) {
_hideWindowZoteroPaneOverlay(win.ZoteroPane.document);
}
}
+
+ if (_progressPopup) {
+ _progressPopup.close();
+ }
+
_locked = false;
_progressMeters = [];
+ _progressPopup = null;
_lastPercentage = null;
}
diff --git a/chrome/locale/en-US/zotero/zotero.properties b/chrome/locale/en-US/zotero/zotero.properties
@@ -647,7 +647,7 @@ sync.status.notYetSynced = Not yet synced
sync.status.lastSync = Last sync:
sync.status.loggingIn = Logging in to sync server
sync.status.gettingUpdatedData = Getting updated data from sync server
-sync.status.processingUpdatedData = Processing updated data
+sync.status.processingUpdatedData = Processing updated data from sync server
sync.status.uploadingData = Uploading data to sync server
sync.status.uploadAccepted = Upload accepted \u2014 waiting for sync server
sync.status.syncingFiles = Syncing files
diff --git a/chrome/skin/default/zotero/zotero.css b/chrome/skin/default/zotero/zotero.css
@@ -208,7 +208,7 @@ label.zotero-text-link {
}
-#zotero-progress-box, #zotero-progress-box
+#zotero-progress-box
{
border: 2px solid #7a0000;
margin: 0;
@@ -217,13 +217,18 @@ label.zotero-text-link {
padding-bottom: 3px;
}
-.zotero-progress-item-icon, .zotero-progress-item-icon
+#zotero-progress-text-headline
+{
+ font-weight: bold;
+}
+
+.zotero-progress-item-icon
{
width: 16px;
height: 16px;
}
-.zotero-progress-item-hbox, .zotero-progress-item-hbox
+.zotero-progress-item-hbox
{
padding-left: 5px;
margin-top: 3px;
@@ -233,6 +238,7 @@ label.zotero-text-link {
.zotero-progress-item-label
{
width: 210px;
+ margin-left: 5px;
}
#zotero-progress-box description