www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | Submodules | README | LICENSE

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:
Mchrome/content/zotero/browser.js | 1-
Mchrome/content/zotero/overlay.js | 17+++++++++++++----
Mchrome/content/zotero/progressWindow.xul | 2+-
Mchrome/content/zotero/xpcom/db.js | 4++++
Mchrome/content/zotero/xpcom/progressWindow.js | 31+++++++++++++++++++------------
Mchrome/content/zotero/xpcom/sync.js | 447++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Mchrome/content/zotero/xpcom/zotero.js | 44+++++++++++++++++++++++++++++++++++++-------
Mchrome/locale/en-US/zotero/zotero.properties | 2+-
Mchrome/skin/default/zotero/zotero.css | 12+++++++++---
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