Use async I/O for attachment (blue dot) column file check in Fx23+

This commit is contained in:
Dan Stillman 2013-08-05 16:31:23 -04:00
parent 86c6611560
commit 675fde2f1a
2 changed files with 114 additions and 27 deletions

View file

@ -2951,12 +2951,48 @@ Zotero.Item.prototype.getFilename = function () {
*
* This is updated only initially and on subsequent getFile() calls.
*/
Zotero.Item.prototype.__defineGetter__('fileExists', function () {
if (this._fileExists === null) {
Zotero.Item.prototype.fileExists = function (cachedOnly) {
if (!cachedOnly && this._fileExists === null) {
this.getFile();
}
return this._fileExists;
});
};
/**
* Asynchronous cached check for file existence, used for items view
*
* This is updated only initially and on subsequent getFile() calls.
*/
Zotero.Item.prototype.fileExistsAsync = function () {
var self = this;
return Q.fcall(function () {
if (self._fileExists !== null) {
return self._fileExists;
}
if (Zotero.platformMajorVersion < 23) {
return self.fileExists();
}
if (!self.isAttachment()) {
throw new Error("Zotero.Item.fileExistsAsync() can only be called on attachment items");
}
if (self.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_URL) {
throw new Error("Zotero.Item.fileExistsAsync() cannot be called on link attachments");
}
var nsIFile = self.getFile(null, true);
Components.utils.import("resource://gre/modules/osfile.jsm");
return Q(OS.File.exists(nsIFile.path))
.then(function(exists) {
self._updateAttachmentStates(exists);
return exists;
});
});
};
/*
@ -3611,16 +3647,46 @@ Zotero.Item.prototype.getBestAttachment = function() {
*
* @return {Integer} 0 (none), 1 (present), -1 (missing)
*/
Zotero.Item.prototype.getBestAttachmentState = function () {
if (this._bestAttachmentState !== null) {
Zotero.Item.prototype.getBestAttachmentState = function (cachedOnly) {
if (cachedOnly || this._bestAttachmentState !== null) {
return this._bestAttachmentState;
}
var itemID = this.getBestAttachment();
this._bestAttachmentState = itemID ? (Zotero.Items.get(itemID).fileExists ? 1 : -1) : 0;
this._bestAttachmentState = itemID
? (Zotero.Items.get(itemID).fileExists() ? 1 : -1)
: 0;
return this._bestAttachmentState;
}
/**
* Return cached state of best attachment for use in items view
*
* @return {Promise:Integer} Promise with 0 (none), 1 (present), -1 (missing)
*/
Zotero.Item.prototype.getBestAttachmentStateAsync = function () {
var self = this;
return Q.fcall(function() {
if (self._bestAttachmentState !== null) {
return self._bestAttachmentState;
}
var itemID = self.getBestAttachment();
if (itemID) {
return Zotero.Items.get(itemID).fileExistsAsync()
.then(function (exists) {
self._bestAttachmentState = exists ? 1 : -1;
});
}
else {
self._bestAttachmentState = 0;
}
})
.then(function () {
return self._bestAttachmentState;
});
}
Zotero.Item.prototype.updateBestAttachmentState = function () {
this._bestAttachmentState = null;
}

View file

@ -598,7 +598,8 @@ Zotero.ItemTreeView.prototype.notify = function(action, type, ids, extraData)
// Clear item type icons
var items = Zotero.Items.get(ids);
for (let i=0; i<items.length; i++) {
delete this._itemImages[items[i].id];
let id = items[i].id;
delete this._itemImages[id];
}
this.refresh();
@ -612,7 +613,7 @@ Zotero.ItemTreeView.prototype.notify = function(action, type, ids, extraData)
var items = Zotero.Items.get(ids);
for each(var item in items) {
var id = item.id;
let id = item.id;
// Make sure row map is up to date
// if we made changes in a previous loop
@ -691,8 +692,9 @@ Zotero.ItemTreeView.prototype.notify = function(action, type, ids, extraData)
var isTrash = itemGroup.isTrash();
var items = Zotero.Items.get(ids);
for each(var item in items) {
let id = item.id;
// Clear item type icon
delete this._itemImages[item.id];
delete this._itemImages[id];
// If not viewing trash and all items were deleted, ignore modify
if (allDeleted && !isTrash && !item.deleted) {
@ -1062,34 +1064,53 @@ Zotero.ItemTreeView.prototype.getImageSrc = function(row, col)
if (this._itemGroup.isTrash()) return false;
var treerow = this._getItemAtRow(row);
var item = treerow.ref;
if ((!this.isContainer(row) || !this.isContainerOpen(row))
&& Zotero.Sync.Storage.getItemDownloadImageNumber(treerow.ref)) {
&& Zotero.Sync.Storage.getItemDownloadImageNumber(item)) {
return '';
}
var itemID = item.id;
if (treerow.level === 0) {
if (treerow.ref.isRegularItem()) {
switch (treerow.ref.getBestAttachmentState()) {
case 1:
return "chrome://zotero/skin/bullet_blue.png";
case -1:
return "chrome://zotero/skin/bullet_blue_empty.png";
default:
return "";
if (item.isRegularItem()) {
let state = item.getBestAttachmentState(true);
if (state !== null) {
switch (state) {
case 1:
return "chrome://zotero/skin/bullet_blue.png";
case -1:
return "chrome://zotero/skin/bullet_blue_empty.png";
default:
return "";
}
}
item.getBestAttachmentStateAsync()
// Refresh cell when promise is fulfilled
.then(function (state) {
this._treebox.invalidateCell(row, col);
}.bind(this))
.done();
}
}
if (treerow.ref.isFileAttachment()) {
if (treerow.ref.fileExists) {
return "chrome://zotero/skin/bullet_blue.png";
}
else {
return "chrome://zotero/skin/bullet_blue_empty.png";
if (item.isFileAttachment()) {
let exists = item.fileExists(true);
if (exists !== null) {
return exists
? "chrome://zotero/skin/bullet_blue.png"
: "chrome://zotero/skin/bullet_blue_empty.png";
}
item.fileExistsAsync()
// Refresh cell when promise is fulfilled
.then(function (exists) {
this._treebox.invalidateCell(row, col);
}.bind(this));
}
}
}
@ -1354,7 +1375,7 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
case 'hasAttachment':
getField = function (row) {
if (row.ref.isAttachment()) {
var state = row.ref.fileExists ? 1 : -1;
var state = row.ref.fileExists() ? 1 : -1;
}
else if (row.ref.isRegularItem()) {
var state = row.ref.getBestAttachmentState();