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()
This commit is contained in:
parent
15c79766e8
commit
e1cc377162
9 changed files with 349 additions and 225 deletions
|
@ -136,7 +136,6 @@ var Zotero_Browser = new function() {
|
|||
Zotero_Browser.progress.show();
|
||||
Zotero_Browser.progress.startCloseTimer(8000);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Zotero.stateCheck()) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
||||
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 + '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'));
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Zotero.pumpGenerator(gen);
|
||||
}
|
||||
catch (e) {
|
||||
Zotero.DB.rollbackTransaction();
|
||||
|
||||
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 + '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'));
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue