Various feeds changes
This commit is contained in:
parent
e7f568d56c
commit
2d46e3d59b
12 changed files with 189 additions and 160 deletions
|
@ -149,14 +149,14 @@ Zotero.CollectionTreeRow.prototype.isWithinEditableGroup = function () {
|
|||
}
|
||||
|
||||
Zotero.CollectionTreeRow.prototype.__defineGetter__('editable', function () {
|
||||
if (this.isTrash() || this.isShare() || this.isBucket() || this.isFeed()) {
|
||||
if (this.isTrash() || this.isShare() || this.isBucket()) {
|
||||
return false;
|
||||
}
|
||||
if (!this.isWithinGroup() || this.isPublications()) {
|
||||
return true;
|
||||
}
|
||||
var libraryID = this.ref.libraryID;
|
||||
if (this.isGroup()) {
|
||||
if (this.isGroup() || this.isFeed()) {
|
||||
return this.ref.editable;
|
||||
}
|
||||
if (this.isCollection() || this.isSearch() || this.isDuplicates() || this.isUnfiled()) {
|
||||
|
|
|
@ -48,6 +48,7 @@ Zotero.CollectionTreeView = function()
|
|||
'collection',
|
||||
'search',
|
||||
'publications',
|
||||
'feed',
|
||||
'share',
|
||||
'group',
|
||||
'feedItem',
|
||||
|
@ -315,7 +316,7 @@ Zotero.CollectionTreeView.prototype.selectWait = Zotero.Promise.method(function
|
|||
* Called by Zotero.Notifier on any changes to collections in the data layer
|
||||
*/
|
||||
Zotero.CollectionTreeView.prototype.notify = Zotero.Promise.coroutine(function* (action, type, ids, extraData) {
|
||||
if (type == 'feed' && action == 'unreadCountUpdated') {
|
||||
if (type == 'feed' && (action == 'unreadCountUpdated' || action == 'statusChanged')) {
|
||||
for (let i=0; i<ids.length; i++) {
|
||||
this._treebox.invalidateRow(this._rowMap['L' + ids[i]]);
|
||||
}
|
||||
|
@ -492,7 +493,7 @@ Zotero.CollectionTreeView.prototype.notify = Zotero.Promise.coroutine(function*
|
|||
case 'feed':
|
||||
case 'group':
|
||||
yield this.reload();
|
||||
yield this.selectByID(currentTreeRow.id);
|
||||
yield this.selectByID("L" + id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -719,6 +720,11 @@ Zotero.CollectionTreeView.prototype.getImageSrc = function(row, col)
|
|||
switch (collectionType) {
|
||||
case 'library':
|
||||
case 'feed':
|
||||
if (treeRow.ref.updating) {
|
||||
collectionType += '-updating';
|
||||
} else if (treeRow.ref.lastCheckError) {
|
||||
collectionType += '-error';
|
||||
}
|
||||
break;
|
||||
|
||||
case 'trash':
|
||||
|
@ -731,6 +737,9 @@ Zotero.CollectionTreeView.prototype.getImageSrc = function(row, col)
|
|||
if (treeRow.ref.id == 'group-libraries-header') {
|
||||
collectionType = 'groups';
|
||||
}
|
||||
else if (treeRow.ref.id == 'feed-libraries-header') {
|
||||
collectionType = 'feedLibrary';
|
||||
}
|
||||
else if (treeRow.ref.id == 'commons-header') {
|
||||
collectionType = 'commons';
|
||||
}
|
||||
|
|
|
@ -29,13 +29,14 @@ Zotero.Feed = function(params = {}) {
|
|||
|
||||
this._feedCleanupAfter = null;
|
||||
this._feedRefreshInterval = null;
|
||||
|
||||
// Feeds are not editable/filesEditable by the user. Remove the setter
|
||||
this.editable = false;
|
||||
|
||||
// Feeds are editable by the user. Remove the setter
|
||||
this.editable = true;
|
||||
Zotero.defineProperty(this, 'editable', {
|
||||
get: function() this._get('_libraryEditable')
|
||||
});
|
||||
|
||||
|
||||
// Feeds are not filesEditable by the user. Remove the setter
|
||||
this.filesEditable = false;
|
||||
Zotero.defineProperty(this, 'filesEditable', {
|
||||
get: function() this._get('_libraryFilesEditable')
|
||||
|
@ -53,22 +54,31 @@ Zotero.Feed = function(params = {}) {
|
|||
return obj[prop];
|
||||
}
|
||||
});
|
||||
this._feedUnreadCount = null;
|
||||
|
||||
this._updating = false;
|
||||
}
|
||||
|
||||
Zotero.Feed._colToProp = function(c) {
|
||||
return "_feed" + Zotero.Utilities.capitalize(c);
|
||||
}
|
||||
|
||||
Zotero.defineProperty(Zotero.Feed, '_unreadCountSQL', {
|
||||
value: "(SELECT COUNT(*) FROM items I JOIN feedItems FeI USING (itemID)"
|
||||
+ " WHERE I.libraryID=F.libraryID AND FeI.readTime IS NULL) AS _feedUnreadCount"
|
||||
});
|
||||
|
||||
Zotero.defineProperty(Zotero.Feed, '_dbColumns', {
|
||||
value: Object.freeze(['name', 'url', 'lastUpdate', 'lastCheck',
|
||||
'lastCheckError', 'cleanupAfter', 'refreshInterval'])
|
||||
});
|
||||
|
||||
Zotero.Feed._colToProp = function(c) {
|
||||
return "_feed" + Zotero.Utilities.capitalize(c);
|
||||
}
|
||||
Zotero.defineProperty(Zotero.Feed, '_primaryDataSQLParts');
|
||||
|
||||
Zotero.defineProperty(Zotero.Feed, '_rowSQLSelect', {
|
||||
value: Zotero.Library._rowSQLSelect + ", "
|
||||
+ Zotero.Feed._dbColumns.map(c => "F." + c + " AS " + Zotero.Feed._colToProp(c)).join(", ")
|
||||
+ ", (SELECT COUNT(*) FROM items I JOIN feedItems FeI USING (itemID)"
|
||||
+ " WHERE I.libraryID=F.libraryID AND FeI.readTime IS NULL) AS feedUnreadCount"
|
||||
+ ", " + Zotero.Feed._unreadCountSQL
|
||||
});
|
||||
|
||||
Zotero.defineProperty(Zotero.Feed, '_rowSQL', {
|
||||
|
@ -89,6 +99,17 @@ Zotero.defineProperty(Zotero.Feed.prototype, 'isFeed', {
|
|||
Zotero.defineProperty(Zotero.Feed.prototype, 'libraryTypes', {
|
||||
value: Object.freeze(Zotero.Feed._super.prototype.libraryTypes.concat(['feed']))
|
||||
});
|
||||
Zotero.defineProperty(Zotero.Feed.prototype, 'unreadCount', {
|
||||
get: function() this._feedUnreadCount
|
||||
});
|
||||
Zotero.defineProperty(Zotero.Feed.prototype, 'updating', {
|
||||
get: function() this._updating,
|
||||
set: function(v) {
|
||||
if (!v == !this._updating) return; // Unchanged
|
||||
this._updating = !!v;
|
||||
Zotero.Notifier.trigger('statusChanged', 'feed', this.id);
|
||||
}
|
||||
});
|
||||
|
||||
(function() {
|
||||
// Create accessors
|
||||
|
@ -185,7 +206,7 @@ Zotero.Feed.prototype._loadDataFromRow = function(row) {
|
|||
this._feedLastUpdate = row._feedLastUpdate || null;
|
||||
this._feedCleanupAfter = parseInt(row._feedCleanupAfter) || null;
|
||||
this._feedRefreshInterval = parseInt(row._feedRefreshInterval) || null;
|
||||
this._feedUnreadCount = parseInt(row.feedUnreadCount);
|
||||
this._feedUnreadCount = parseInt(row._feedUnreadCount);
|
||||
}
|
||||
|
||||
Zotero.Feed.prototype._reloadFromDB = Zotero.Promise.coroutine(function* () {
|
||||
|
@ -218,7 +239,7 @@ Zotero.Feed.prototype._initSave = Zotero.Promise.coroutine(function* (env) {
|
|||
Zotero.Feed.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
|
||||
yield Zotero.Feed._super.prototype._saveData.apply(this, arguments);
|
||||
|
||||
Zotero.debug("Saving feed data for collection " + this.id);
|
||||
Zotero.debug("Saving feed data for library " + this.id);
|
||||
|
||||
let changedCols = [], params = [];
|
||||
for (let i=0; i<Zotero.Feed._dbColumns.length; i++) {
|
||||
|
@ -268,21 +289,17 @@ Zotero.Feed.prototype._finalizeSave = Zotero.Promise.coroutine(function* (env) {
|
|||
}
|
||||
});
|
||||
|
||||
Zotero.Feed.prototype._finalizeErase = Zotero.Promise.method(function(env) {
|
||||
Zotero.Feeds.unregister(this.libraryID);
|
||||
return Zotero.Feed._super.prototype._finalizeErase.apply(this, arguments);
|
||||
});
|
||||
|
||||
Zotero.Feed.prototype.getExpiredFeedItemIDs = Zotero.Promise.coroutine(function* () {
|
||||
let sql = "SELECT itemID AS id FROM feedItems "
|
||||
+ "LEFT JOIN libraryItems LI USING (itemID)"
|
||||
+ "WHERE LI.libraryID=?"
|
||||
+ "WHERE readTime IS NOT NULL "
|
||||
+ "AND (julianday(readTime, 'utc') + (?) - julianday('now', 'utc')) > 0";
|
||||
let expiredIDs = yield Zotero.DB.queryAsync(sql, [{int: this.cleanupAfter}]);
|
||||
let expiredIDs = yield Zotero.DB.queryAsync(sql, [this.id, {int: this.cleanupAfter}]);
|
||||
return expiredIDs.map(row => row.id);
|
||||
});
|
||||
|
||||
Zotero.Feed.prototype._updateFeed = Zotero.Promise.coroutine(function* () {
|
||||
let errorMessage = '';
|
||||
Zotero.Feed.prototype.clearExpiredItems = Zotero.Promise.coroutine(function* () {
|
||||
try {
|
||||
// Clear expired items
|
||||
if (this.cleanupAfter) {
|
||||
|
@ -299,10 +316,16 @@ Zotero.Feed.prototype._updateFeed = Zotero.Promise.coroutine(function* () {
|
|||
Zotero.debug("Error clearing expired feed items.");
|
||||
Zotero.debug(e);
|
||||
}
|
||||
});
|
||||
|
||||
Zotero.Feed.prototype._updateFeed = Zotero.Promise.coroutine(function* () {
|
||||
this.updating = true;
|
||||
this.lastCheckError = null;
|
||||
|
||||
yield this.clearExpiredItems();
|
||||
try {
|
||||
let fr = new Zotero.FeedReader(this.url);
|
||||
let itemIterator = fr.itemIterator;
|
||||
let itemIterator = new fr.ItemIterator();
|
||||
let item, toAdd = [], processedGUIDs = [];
|
||||
while (item = yield itemIterator.next().value) {
|
||||
if (item.dateModified && this.lastUpdate
|
||||
|
@ -331,6 +354,7 @@ Zotero.Feed.prototype._updateFeed = Zotero.Promise.coroutine(function* () {
|
|||
feedItem.libraryID = this.id;
|
||||
} else {
|
||||
Zotero.debug("Feed item " + item.guid + " already in library.");
|
||||
|
||||
if (item.dateModified && feedItem.dateModified
|
||||
&& feedItem.dateModified == item.dateModified
|
||||
) {
|
||||
|
@ -353,19 +377,23 @@ Zotero.Feed.prototype._updateFeed = Zotero.Promise.coroutine(function* () {
|
|||
// Save in reverse order
|
||||
let savePromises = new Array(toAdd.length);
|
||||
for (let i=toAdd.length-1; i>=0; i--) {
|
||||
yield toAdd[i].save({skipEditCheck: true, setDateModified: true});
|
||||
// Saving currently has to happen sequentially so as not to violate the
|
||||
// unique constraints in dataValues (FIXME)
|
||||
yield toAdd[i].save({skipEditCheck: true});
|
||||
}
|
||||
|
||||
this.lastUpdate = Zotero.Date.dateToSQL(new Date(), true);
|
||||
} catch(e) {
|
||||
Zotero.debug("Error processing feed from " + this.url);
|
||||
Zotero.debug(e);
|
||||
errorMessage = e.message || 'Error processing feed';
|
||||
}
|
||||
|
||||
catch (e) {
|
||||
if (e.message) {
|
||||
Zotero.debug("Error processing feed from " + this.url);
|
||||
Zotero.debug(e);
|
||||
}
|
||||
this.lastCheckError = e.message || 'Error processing feed';
|
||||
}
|
||||
this.lastCheck = Zotero.Date.dateToSQL(new Date(), true);
|
||||
this.lastCheckError = errorMessage || null;
|
||||
yield this.saveTx({skipEditCheck: true});
|
||||
this.updating = false;
|
||||
});
|
||||
|
||||
Zotero.Feed.prototype.updateFeed = function() {
|
||||
|
@ -375,17 +403,27 @@ Zotero.Feed.prototype.updateFeed = function() {
|
|||
});
|
||||
}
|
||||
|
||||
Zotero.Feed.prototype.erase = Zotero.Promise.coroutine(function* () {
|
||||
yield this.loadChildItems();
|
||||
let childItemIDs = this.getChildItems(true, true);
|
||||
Zotero.Feed.prototype._finalizeErase = Zotero.Promise.coroutine(function* (){
|
||||
let notifierData = {};
|
||||
notifierData[this.libraryID] = {
|
||||
libraryID: this.libraryID
|
||||
};
|
||||
Zotero.Notifier.trigger('delete', 'feed', this.id, notifierData);
|
||||
Zotero.Feeds.unregister(this.libraryID);
|
||||
return Zotero.Feed._super.prototype._finalizeErase.call(this);
|
||||
});
|
||||
|
||||
Zotero.Feed.prototype.erase = Zotero.Promise.coroutine(function* (deleteItems) {
|
||||
let childItemIDs = yield Zotero.FeedItems.getAll(this.id, false, false, true);
|
||||
yield Zotero.FeedItems.erase(childItemIDs);
|
||||
return Zotero.Feed._super.prototype.erase.call(this); // Don't tell it to delete child items. They're already gone
|
||||
})
|
||||
|
||||
yield Zotero.Feed._super.prototype.erase.call(this);
|
||||
});
|
||||
|
||||
Zotero.Feed.prototype.updateUnreadCount = Zotero.Promise.coroutine(function* () {
|
||||
let sql = "SELECT " + this._ObjectsClass._primaryDataSQLParts.feedUnreadCount
|
||||
+ this._ObjectsClass.primaryDataSQLFrom
|
||||
+ " AND O.libraryID=?";
|
||||
let sql = "SELECT " + Zotero.Feed._unreadCountSQL
|
||||
+ " FROM feeds F JOIN libraries L USING (libraryID)"
|
||||
+ " WHERE L.libraryID=?";
|
||||
let newCount = yield Zotero.DB.valueQueryAsync(sql, [this.id]);
|
||||
|
||||
if (newCount != this._feedUnreadCount) {
|
||||
|
|
|
@ -132,38 +132,6 @@ Zotero.FeedItem.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
|
|||
yield Zotero.DB.queryAsync(sql, [env.id, this.guid, this._feedItemReadTime]);
|
||||
|
||||
this._clearChanged('feedItemData');
|
||||
|
||||
/* let itemID;
|
||||
if (env.isNew) {
|
||||
// For new items, run this first so we get an item ID
|
||||
yield Zotero.FeedItem._super.prototype._saveData.apply(this, arguments);
|
||||
itemID = env.id;
|
||||
} else {
|
||||
itemID = this.id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!env.isNew) {
|
||||
if (this.hasChanged()) {
|
||||
yield Zotero.FeedItem._super.prototype._saveData.apply(this, arguments);
|
||||
} else {
|
||||
env.skipPrimaryDataReload = true;
|
||||
}
|
||||
Zotero.Notifier.trigger('modify', 'feedItem', itemID);
|
||||
} else {
|
||||
Zotero.Notifier.trigger('add', 'feedItem', itemID);
|
||||
}
|
||||
|
||||
if (env.collectionsAdded || env.collectionsRemoved) {
|
||||
let affectedCollections = (env.collectionsAdded || [])
|
||||
.concat(env.collectionsRemoved || []);
|
||||
if (affectedCollections.length) {
|
||||
let feeds = yield Zotero.Feeds.getAsync(affectedCollections);
|
||||
for (let i=0; i<feeds.length; i++) {
|
||||
feeds[i].updateUnreadCount();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -174,7 +142,6 @@ Zotero.FeedItem.prototype.toggleRead = Zotero.Promise.coroutine(function* (state
|
|||
if (changed) {
|
||||
yield this.save({skipEditCheck: true, skipDateModifiedUpdate: true});
|
||||
|
||||
yield this.loadCollections();
|
||||
let feed = Zotero.Feeds.get(this.libraryID);
|
||||
feed.updateUnreadCount();
|
||||
}
|
||||
|
|
|
@ -94,14 +94,25 @@ Zotero.FeedItems = new Proxy(function() {
|
|||
return this.getAsync(id);
|
||||
});
|
||||
|
||||
this.toggleReadById = Zotero.Promise.coroutine(function* (ids, state) {
|
||||
this.toggleReadByID = Zotero.Promise.coroutine(function* (ids, state) {
|
||||
if (!Array.isArray(ids)) {
|
||||
if (typeof ids != 'string') throw new Error('ids must be a string or array in Zotero.FeedItems.toggleReadById');
|
||||
if (typeof ids != 'string') throw new Error('ids must be a string or array in Zotero.FeedItems.toggleReadByID');
|
||||
|
||||
ids = [ids];
|
||||
}
|
||||
|
||||
let items = yield this.getAsync(ids);
|
||||
|
||||
if (state == undefined) {
|
||||
// If state undefined, toggle read if at least one unread
|
||||
state = true;
|
||||
for (let item of items) {
|
||||
if (item.isRead) {
|
||||
state = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i=0; i<items.length; i++) {
|
||||
items[i].toggleRead(state);
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ Zotero.Feeds = new function() {
|
|||
.map(id => Zotero.Libraries.get(id));
|
||||
}
|
||||
|
||||
this.get = Zotero.Libraries.get;
|
||||
this.get = Zotero.Libraries.get.bind(Zotero.Libraries);
|
||||
|
||||
this.haveFeeds = function() {
|
||||
if (!this._cache) throw new Error("Zotero.Feeds cache is not initialized");
|
||||
|
@ -154,8 +154,8 @@ Zotero.Feeds = new function() {
|
|||
let sql = "SELECT libraryID AS id FROM feeds "
|
||||
+ "WHERE refreshInterval IS NOT NULL "
|
||||
+ "AND ( lastCheck IS NULL "
|
||||
+ "OR (julianday(lastCheck, 'utc') + (refreshInterval/1440) - julianday('now', 'utc')) <= 0 )";
|
||||
let needUpdate = yield Zotero.DB.queryAsync(sql).map(row => row.id);
|
||||
+ "OR (julianday(lastCheck, 'utc') + (refreshInterval/1440.0) - julianday('now', 'utc')) <= 0 )";
|
||||
let needUpdate = (yield Zotero.DB.queryAsync(sql)).map(row => row.id);
|
||||
Zotero.debug("Running update for feeds: " + needUpdate.join(', '));
|
||||
let feeds = Zotero.Libraries.get(needUpdate);
|
||||
let updatePromises = [];
|
||||
|
|
|
@ -133,9 +133,10 @@ Zotero.Items = function() {
|
|||
* @param {Integer} libraryID
|
||||
* @param {Boolean} [onlyTopLevel=false] If true, don't include child items
|
||||
* @param {Boolean} [includeDeleted=false] If true, include deleted items
|
||||
* @return {Promise<Array<Zotero.Item>>}
|
||||
* @param {Boolean} [onlyIDs=false] If true, resolves only with IDs
|
||||
* @return {Promise<Array<Zotero.Item|Integer>>}
|
||||
*/
|
||||
this.getAll = Zotero.Promise.coroutine(function* (libraryID, onlyTopLevel, includeDeleted) {
|
||||
this.getAll = Zotero.Promise.coroutine(function* (libraryID, onlyTopLevel, includeDeleted, onlyIDs=false) {
|
||||
var sql = 'SELECT A.itemID FROM items A';
|
||||
if (onlyTopLevel) {
|
||||
sql += ' LEFT JOIN itemNotes B USING (itemID) '
|
||||
|
@ -150,6 +151,9 @@ Zotero.Items = function() {
|
|||
}
|
||||
sql += " AND libraryID=?";
|
||||
var ids = yield Zotero.DB.columnQueryAsync(sql, libraryID);
|
||||
if (onlyIDs) {
|
||||
return ids;
|
||||
}
|
||||
return this.getAsync(ids);
|
||||
});
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
*
|
||||
* @property {Zotero.Promise<Object>} feedProperties An object
|
||||
* representing feed properties
|
||||
* @property {Zotero.Promise<FeedItem>*} itemIterator Returns an iterator
|
||||
* @property {Zotero.Promise<FeedItem>*} ItemIterator Returns an iterator
|
||||
* for feed items. The iterator returns FeedItem promises that have to be
|
||||
* resolved before requesting the next promise. When all items are exhausted.
|
||||
* the promise resolves to null.
|
||||
|
@ -170,17 +170,10 @@ Zotero.FeedReader = new function() {
|
|||
}
|
||||
|
||||
/*
|
||||
* Format JS date as SQL date + time zone offset
|
||||
* Format JS date as SQL date
|
||||
*/
|
||||
function formatDate(date) {
|
||||
let offset = (date.getTimezoneOffset() / 60) * -1;
|
||||
let absOffset = Math.abs(offset);
|
||||
offset = offset
|
||||
? ' ' + (offset < 0 ? '-' : '+')
|
||||
+ Zotero.Utilities.lpad(Math.floor(absOffset), '0', 2)
|
||||
+ ('' + ( (absOffset - Math.floor(absOffset)) || '' )).substr(1) // Get ".5" fraction or "" otherwise
|
||||
: '';
|
||||
return Zotero.Date.dateToSQL(date, false) + offset;
|
||||
return Zotero.Date.dateToSQL(date, true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -268,7 +261,6 @@ Zotero.FeedReader = new function() {
|
|||
if (!item.dateModified) {
|
||||
// When there's no reliable modification date, we can assume that item doesn't get updated
|
||||
Zotero.debug("FeedReader: Feed item missing a modification date (" + item.guid + ")");
|
||||
item.dateModified = null;
|
||||
}
|
||||
|
||||
if (!item.date && item.dateModified) {
|
||||
|
@ -470,7 +462,9 @@ Zotero.FeedReader = new function() {
|
|||
|
||||
Zotero.debug("FeedReader: Fetching feed from " + feedUrl.spec);
|
||||
|
||||
this._channel = ios.newChannelFromURI(feedUrl);
|
||||
this._channel = ios.newChannelFromURI2(feedUrl, null,
|
||||
Services.scriptSecurityManager.getSystemPrincipal(), null,
|
||||
Ci.nsILoadInfo.SEC_NORMAL, Ci.nsIContentPolicy.TYPE_OTHER);
|
||||
this._channel.asyncOpen(feedProcessor, null); // Sends an HTTP request
|
||||
}
|
||||
|
||||
|
@ -486,21 +480,25 @@ Zotero.FeedReader = new function() {
|
|||
* is terminated ahead of time, in which case it will be rejected with the reason
|
||||
* for termination.
|
||||
*/
|
||||
Zotero.defineProperty(FeedReader.prototype, 'itemIterator', {
|
||||
Zotero.defineProperty(FeedReader.prototype, 'ItemIterator', {
|
||||
get: function() {
|
||||
let items = this._feedItems;
|
||||
return new function() {
|
||||
let i = 0;
|
||||
this.next = function() {
|
||||
let item = items[i++];
|
||||
return {
|
||||
value: item ? item.promise : null,
|
||||
done: i >= items.length
|
||||
};
|
||||
|
||||
let iterator = function() {
|
||||
this.index = 0;
|
||||
};
|
||||
|
||||
iterator.prototype.next = function() {
|
||||
let item = items[this.index++];
|
||||
return {
|
||||
value: item ? item.promise : null,
|
||||
done: this.index >= items.length
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return iterator;
|
||||
}
|
||||
});
|
||||
}, {lazy: true});
|
||||
|
||||
/*
|
||||
* Terminate feed processing at any given time
|
||||
|
@ -521,8 +519,8 @@ Zotero.FeedReader = new function() {
|
|||
}
|
||||
|
||||
// Close feed connection
|
||||
if (channel.isPending) {
|
||||
channel.cancel(Components.results.NS_BINDING_ABORTED);
|
||||
if (this._channel.isPending) {
|
||||
this._channel.cancel(Components.results.NS_BINDING_ABORTED);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -133,6 +133,14 @@ Zotero.URI = new function () {
|
|||
}
|
||||
|
||||
|
||||
this.getFeedItemURI = function(feedItem) {
|
||||
return this.getItemURI(feedItem);
|
||||
}
|
||||
|
||||
this.getFeedItemPath = function(feedItem) {
|
||||
return this.getItemPath(feedItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return URI of collection, which might be a local URI if user hasn't synced
|
||||
*/
|
||||
|
@ -148,6 +156,14 @@ Zotero.URI = new function () {
|
|||
return this._getObjectPath(collection);
|
||||
}
|
||||
|
||||
this.getFeedURI = function(feed) {
|
||||
return this.getLibraryURI(feed);
|
||||
}
|
||||
|
||||
this.getFeedPath = function(feed) {
|
||||
return this.getLibraryPath(feed);
|
||||
}
|
||||
|
||||
|
||||
this.getGroupsURL = function () {
|
||||
return ZOTERO_CONFIG.WWW_BASE_URL + "groups";
|
||||
|
@ -172,7 +188,7 @@ Zotero.URI = new function () {
|
|||
return path;
|
||||
}
|
||||
|
||||
if (obj instanceof Zotero.Item) {
|
||||
if (obj instanceof Zotero.Item || obj instanceof Zotero.Feed) {
|
||||
return path + '/items/' + obj.key;
|
||||
}
|
||||
|
||||
|
@ -208,6 +224,9 @@ Zotero.URI = new function () {
|
|||
return this._getURIObject(itemURI, 'item');
|
||||
}
|
||||
|
||||
this.getURIFeedItem = function (feedItemURI) {
|
||||
return this._getURIObject(feedItemURI, 'feedItem');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} itemURI
|
||||
|
@ -264,6 +283,11 @@ Zotero.URI = new function () {
|
|||
let library = this._getURIObjectLibrary(libraryURI);
|
||||
return library ? library.id : false;
|
||||
}
|
||||
|
||||
|
||||
this.getURIFeed = function (feedURI) {
|
||||
return this._getURIObjectLibrary(feedURI, 'feed');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -522,22 +522,7 @@ var ZoteroPane = new function()
|
|||
}
|
||||
|
||||
let itemIDs = this.getSelectedItems(true);
|
||||
Zotero.FeedItems.getAsync(itemIDs)
|
||||
.then(function(feedItems) {
|
||||
// Determine what most items are set to;
|
||||
let allUnread = true;
|
||||
for (let item of feedItems) {
|
||||
if (item.isRead) {
|
||||
allUnread = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If something is unread, toggle all read by default
|
||||
for (let i=0; i<feedItems.length; i++) {
|
||||
feedItems[i].toggleRead(!allUnread);
|
||||
}
|
||||
});
|
||||
Zotero.FeedItems.toggleReadByID(itemIDs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -866,7 +851,7 @@ var ZoteroPane = new function()
|
|||
return collection.saveTx();
|
||||
});
|
||||
|
||||
this.newFeed = Zotero.Promise.coroutine(function() {
|
||||
this.newFeed = Zotero.Promise.coroutine(function* () {
|
||||
let data = {};
|
||||
window.openDialog('chrome://zotero/content/feedSettings.xul',
|
||||
null, 'centerscreen, modal', data);
|
||||
|
@ -877,7 +862,7 @@ var ZoteroPane = new function()
|
|||
feed.refreshInterval = data.ttl;
|
||||
feed.cleanupAfter = data.cleanAfter;
|
||||
yield feed.save({skipEditCheck: true});
|
||||
Zotero.Feeds.scheduleNextFeedCheck();
|
||||
yield feed.updateFeed();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1774,48 +1759,40 @@ var ZoteroPane = new function()
|
|||
buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING
|
||||
+ ps.BUTTON_POS_1 * ps.BUTTON_TITLE_CANCEL;
|
||||
if (this.collectionsView.selection.count == 1) {
|
||||
if (collectionTreeRow.isCollection())
|
||||
{
|
||||
var title, message;
|
||||
// Work out the required title and message
|
||||
if (collectionTreeRow.isCollection()) {
|
||||
if (deleteItems) {
|
||||
var index = ps.confirmEx(
|
||||
null,
|
||||
Zotero.getString('pane.collections.deleteWithItems.title'),
|
||||
Zotero.getString('pane.collections.deleteWithItems'),
|
||||
buttonFlags,
|
||||
Zotero.getString('pane.collections.deleteWithItems.title'),
|
||||
"", "", "", {}
|
||||
);
|
||||
title = Zotero.getString('pane.collections.deleteWithItems.title');
|
||||
message = Zotero.getString('pane.collections.deleteWithItems');
|
||||
}
|
||||
else {
|
||||
var index = ps.confirmEx(
|
||||
null,
|
||||
Zotero.getString('pane.collections.delete.title'),
|
||||
Zotero.getString('pane.collections.delete')
|
||||
title = Zotero.getString('pane.collections.delete.title');
|
||||
message = Zotero.getString('pane.collections.delete')
|
||||
+ "\n\n"
|
||||
+ Zotero.getString('pane.collections.delete.keepItems'),
|
||||
buttonFlags,
|
||||
Zotero.getString('pane.collections.delete.title'),
|
||||
"", "", "", {}
|
||||
);
|
||||
}
|
||||
if (index == 0) {
|
||||
this.collectionsView.deleteSelection(deleteItems);
|
||||
+ Zotero.getString('pane.collections.delete.keepItems');
|
||||
}
|
||||
}
|
||||
else if (collectionTreeRow.isSearch())
|
||||
{
|
||||
|
||||
var index = ps.confirmEx(
|
||||
null,
|
||||
Zotero.getString('pane.collections.deleteSearch.title'),
|
||||
Zotero.getString('pane.collections.deleteSearch'),
|
||||
buttonFlags,
|
||||
Zotero.getString('pane.collections.deleteSearch.title'),
|
||||
"", "", "", {}
|
||||
);
|
||||
if (index == 0) {
|
||||
this.collectionsView.deleteSelection();
|
||||
}
|
||||
else if (collectionTreeRow.isFeed()) {
|
||||
title = Zotero.getString('pane.feed.deleteWithItems.title');
|
||||
message = Zotero.getString('pane.feed.deleteWithItems');
|
||||
}
|
||||
else if (collectionTreeRow.isSearch()) {
|
||||
title = Zotero.getString('pane.collections.deleteSearch.title');
|
||||
message = Zotero.getString('pane.collections.deleteSearch');
|
||||
}
|
||||
|
||||
// Display prompt
|
||||
var index = ps.confirmEx(
|
||||
null,
|
||||
title,
|
||||
message,
|
||||
buttonFlags,
|
||||
title,
|
||||
"", "", "", {}
|
||||
);
|
||||
if (index == 0) {
|
||||
this.collectionsView.deleteSelection(deleteItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2230,6 +2207,7 @@ var ZoteroPane = new function()
|
|||
"newCollection",
|
||||
"newSavedSearch",
|
||||
"newSubcollection",
|
||||
"newFeed",
|
||||
"refreshFeed",
|
||||
"sep1",
|
||||
"showDuplicates",
|
||||
|
|
BIN
chrome/skin/default/zotero/treesource-feed-error.png
Normal file
BIN
chrome/skin/default/zotero/treesource-feed-error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
BIN
chrome/skin/default/zotero/treesource-feed-updating.png
Normal file
BIN
chrome/skin/default/zotero/treesource-feed-updating.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.5 KiB |
Loading…
Reference in a new issue