Fix various issues with rapid UI/data changes due to asyncification

This commit is contained in:
Dan Stillman 2015-05-05 02:35:04 -04:00
parent fc428f8e1b
commit 02a36eab9b
8 changed files with 69 additions and 42 deletions

View file

@ -600,20 +600,18 @@
<method name="clearVisible"> <method name="clearVisible">
<body><![CDATA[ <body><![CDATA[
return Zotero.spawn(function* () { var tagsToggleBox = this.id('tags-toggle');
var tagsToggleBox = this.id('tags-toggle');
var labels = Zotero.Utilities.xpath(tagsToggleBox, 'label[@selected="true"]');
var labels = Zotero.Utilities.xpath(tagsToggleBox, 'label[@selected="true"]'); for (var i=0; i<labels.length; i++){
for (var i=0; i<labels.length; i++){ var label = labels[i];
var label = labels[i]; label.setAttribute('selected', 'false');
label.setAttribute('selected', 'false'); delete this.selection[label.value];
delete this.selection[label.value]; }
}
if (this.onchange) {
if (this.onchange) { this.onchange();
this.onchange(); }
}
}, this);
]]></body> ]]></body>
</method> </method>

View file

@ -93,7 +93,12 @@ var ZoteroOverlay = new function()
prefBranch.clearUserPref('statusBarIcon'); prefBranch.clearUserPref('statusBarIcon');
// Add toolbar icon // Add toolbar icon
Services.scriptloader.loadSubScript("chrome://zotero/content/icon.js", {}, "UTF-8"); try {
Services.scriptloader.loadSubScript("chrome://zotero/content/icon.js", {}, "UTF-8");
}
catch (e) {
Zotero.logError(e);
}
// TODO: Add only when progress window is open // TODO: Add only when progress window is open
document.getElementById('appcontent').addEventListener('mousemove', Zotero.ProgressWindowSet.updateTimers, false); document.getElementById('appcontent').addEventListener('mousemove', Zotero.ProgressWindowSet.updateTimers, false);

View file

@ -2392,7 +2392,7 @@ Zotero.CollectionTreeRow.prototype.getItems = Zotero.Promise.coroutine(function*
if (!ids.length) { if (!ids.length) {
return [] return []
} }
return Zotero.Items.get(ids); return Zotero.Items.getAsync(ids);
}); });
Zotero.CollectionTreeRow.prototype.getSearchResults = Zotero.Promise.coroutine(function* (asTempTable) { Zotero.CollectionTreeRow.prototype.getSearchResults = Zotero.Promise.coroutine(function* (asTempTable) {
@ -2493,7 +2493,7 @@ Zotero.CollectionTreeRow.prototype.getSearchObject = Zotero.Promise.coroutine(fu
* *
* @return {Promise} * @return {Promise}
*/ */
Zotero.CollectionTreeRow.prototype.getChildTags = Zotero.Promise.method(function () { Zotero.CollectionTreeRow.prototype.getChildTags = Zotero.Promise.coroutine(function* () {
switch (this.type) { switch (this.type) {
// TODO: implement? // TODO: implement?
case 'share': case 'share':
@ -2502,8 +2502,8 @@ Zotero.CollectionTreeRow.prototype.getChildTags = Zotero.Promise.method(function
case 'bucket': case 'bucket':
return false; return false;
} }
var results = yield this.getSearchResults(true);
return Zotero.Tags.getAllWithinSearchResults(this.getSearchResults(true)); return Zotero.Tags.getAllWithinSearchResults(results);
}); });

View file

@ -155,13 +155,11 @@ Zotero.Tags = new function() {
/** /**
* Get all tags within the items of a temporary table of search results * Get all tags within the items of a temporary table of search results
* *
* @param {String|Promise<String>} tmpTable Temporary table with items to use * @param {String} tmpTable Temporary table with items to use
* @param {Array} [types] Array of tag types to fetch * @param {Array} [types] Array of tag types to fetch
* @return {Promise<Object>} Promise for object with tag data in API JSON format, keyed by tagID * @return {Promise<Object>} Promise for object with tag data in API JSON format, keyed by tagID
*/ */
this.getAllWithinSearchResults = Zotero.Promise.coroutine(function* (tmpTable, types) { this.getAllWithinSearchResults = Zotero.Promise.coroutine(function* (tmpTable, types) {
tmpTable = yield Zotero.Promise.resolve(tmpTable);
var sql = "SELECT DISTINCT name AS tag, type FROM itemTags " var sql = "SELECT DISTINCT name AS tag, type FROM itemTags "
+ "JOIN tags USING (tagID) WHERE itemID IN " + "JOIN tags USING (tagID) WHERE itemID IN "
+ "(SELECT itemID FROM " + tmpTable + ") "; + "(SELECT itemID FROM " + tmpTable + ") ";

View file

@ -64,10 +64,10 @@ Zotero.ItemTreeView.prototype.type = 'item';
/** /**
* Called by the tree itself * Called by the tree itself
*/ */
Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (treebox) Zotero.ItemTreeView.prototype.setTree = Zotero.serial(Zotero.Promise.coroutine(function* (treebox)
{ {
try { try {
//Zotero.debug("Calling setTree()"); Zotero.debug("Setting item tree");
var start = Date.now(); var start = Date.now();
// Try to set the window document if not yet set // Try to set the window document if not yet set
if (treebox && !this._ownerDocument) { if (treebox && !this._ownerDocument) {
@ -85,7 +85,13 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
} }
if (!treebox) { if (!treebox) {
Components.utils.reportError("Passed treebox empty in setTree()"); Zotero.debug("Treebox not passed in setTree()", 2);
return;
}
if (!this._ownerDocument) {
Zotero.debug("No owner document in setTree()", 2);
return;
} }
this._treebox = treebox; this._treebox = treebox;
@ -103,8 +109,6 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
return; return;
} }
yield Zotero.DB.waitForTransaction();
yield this.refresh(); yield this.refresh();
// Add a keypress listener for expand/collapse // Add a keypress listener for expand/collapse
@ -235,10 +239,8 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
tree._handleEnter = function () {}; tree._handleEnter = function () {};
yield this.sort(); yield this.sort();
yield this.expandMatchParents(); yield this.expandMatchParents();
if (this._ownerDocument.defaultView.ZoteroPane_Local) { if (this._ownerDocument.defaultView.ZoteroPane_Local) {
this._ownerDocument.defaultView.ZoteroPane_Local.clearItemsPaneMessage(); this._ownerDocument.defaultView.ZoteroPane_Local.clearItemsPaneMessage();
} }
@ -256,13 +258,14 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
yield this._runListeners('load'); yield this._runListeners('load');
} }
catch (e) { catch (e) {
Zotero.debug(e, 1);
Components.utils.reportError(e); Components.utils.reportError(e);
if (this.onError) { if (this.onError) {
this.onError(e); this.onError(e);
} }
throw e; throw e;
}; }
}); }));
/** /**
@ -331,27 +334,32 @@ Zotero.ItemTreeView.prototype.refresh = Zotero.serial(Zotero.Promise.coroutine(f
var added = 0; var added = 0;
for (let i=0, len=newItems.length; i < len; i++) { for (let i=0, len=newItems.length; i < len; i++) {
let item = newItems[i];
// Only add regular items if sourcesOnly is set // Only add regular items if sourcesOnly is set
if (this._sourcesOnly && !newItems[i].isRegularItem()) { if (this._sourcesOnly && !item.isRegularItem()) {
continue; continue;
} }
// Don't add child items directly (instead mark their parents for // Don't add child items directly (instead mark their parents for
// inclusion below) // inclusion below)
let parentItemID = newItems[i].parentItemID; let parentItemID = item.parentItemID;
if (parentItemID) { if (parentItemID) {
newSearchParentIDs[parentItemID] = true; newSearchParentIDs[parentItemID] = true;
} }
// Add top-level items // Add top-level items
else { else {
yield item.loadItemData();
yield item.loadCollections();
this._addRow( this._addRow(
newRows, newRows,
new Zotero.ItemTreeRow(newItems[i], 0, false), new Zotero.ItemTreeRow(item, 0, false),
added + 1 added + 1
); );
added++; added++;
} }
newSearchItemIDs[newItems[i].id] = true; newSearchItemIDs[item.id] = true;
} }
// Add parents of matches if not matches themselves // Add parents of matches if not matches themselves
@ -925,9 +933,13 @@ Zotero.ItemTreeView.prototype.notify = Zotero.Promise.coroutine(function* (actio
} }
//this._treebox.endUpdateBatch(); //this._treebox.endUpdateBatch();
var promise = this._getItemSelectedPromise(); if (madeChanges) {
var promise = this._getItemSelectedPromise();
}
this.selection.selectEventsSuppressed = false; this.selection.selectEventsSuppressed = false;
yield promise; if (madeChanges) {
yield promise;
}
}); });
/* /*

View file

@ -1111,9 +1111,10 @@ var ZoteroPane = new function()
this.onCollectionSelected = Zotero.Promise.coroutine(function* () { this.onCollectionSelected = Zotero.Promise.coroutine(function* () {
yield Zotero.DB.waitForTransaction();
var collectionTreeRow = this.getCollectionTreeRow(); var collectionTreeRow = this.getCollectionTreeRow();
if (!collectionTreeRow) {
return;
}
if (this.itemsView && this.itemsView.collectionTreeRow == collectionTreeRow) { if (this.itemsView && this.itemsView.collectionTreeRow == collectionTreeRow) {
Zotero.debug("Collection selection hasn't changed"); Zotero.debug("Collection selection hasn't changed");
@ -1131,7 +1132,12 @@ var ZoteroPane = new function()
// Clear quick search and tag selector when switching views // Clear quick search and tag selector when switching views
document.getElementById('zotero-tb-search').value = ""; document.getElementById('zotero-tb-search').value = "";
yield document.getElementById('zotero-tag-selector').clearAll();
// XBL functions might not yet be available
var tagSelector = document.getElementById('zotero-tag-selector');
if (tagSelector.clearAll) {
tagSelector.clearAll();
}
// Not necessary with seltype="cell", which calls nsITreeView::isSelectable() // Not necessary with seltype="cell", which calls nsITreeView::isSelectable()
/*if (collectionTreeRow.isSeparator()) { /*if (collectionTreeRow.isSeparator()) {

View file

@ -1,3 +1,5 @@
"use strict";
describe("Zotero.CollectionTreeView", function() { describe("Zotero.CollectionTreeView", function() {
var win, collectionsView; var win, collectionsView;

View file

@ -1,11 +1,17 @@
describe("Zotero.DB", function() { describe("Zotero.DB", function() {
var tmpTable = "tmpDBTest"; var tmpTable = "tmpDBTest";
before(function* () {
this.timeout(5000);
Zotero.debug("Waiting for DB activity to settle");
yield Zotero.DB.waitForTransaction();
yield Zotero.Promise.delay(1000);
});
beforeEach(function* () { beforeEach(function* () {
Zotero.DB.queryAsync("DROP TABLE IF EXISTS " + tmpTable); yield Zotero.DB.queryAsync("DROP TABLE IF EXISTS " + tmpTable);
}); });
after(function* () { after(function* () {
Zotero.DB.queryAsync("DROP TABLE IF EXISTS " + tmpTable); yield Zotero.DB.queryAsync("DROP TABLE IF EXISTS " + tmpTable);
}); });
describe("#executeTransaction()", function () { describe("#executeTransaction()", function () {