Update tab titles independently of the reader (#4813)
Move handling of tabs' renaming when an item is modified from Reader into Zotero_Tabs, so that the titles of unloaded tabs can get properly renamed. Have the Reader and Zotero_Tabs share Zotero.Item#getTabTitle() to handle title updates in both tabs and standalone reader windows. Fixes: #4646
This commit is contained in:
parent
9f8c5c8581
commit
e9a19cb7a1
3 changed files with 98 additions and 46 deletions
|
@ -84,6 +84,19 @@ var Zotero_Tabs = new function () {
|
||||||
this._tabsMenuFocusedIndex = 0;
|
this._tabsMenuFocusedIndex = 0;
|
||||||
this._tabsMenuIgnoreMouseover = false;
|
this._tabsMenuIgnoreMouseover = false;
|
||||||
|
|
||||||
|
// Keep track of item modifications to update the title
|
||||||
|
Zotero.Notifier.registerObserver(this, ['item'], 'tabs');
|
||||||
|
|
||||||
|
// Update the title when pref of title format is changed
|
||||||
|
Zotero.Prefs.registerObserver('tabs.title.reader', async () => {
|
||||||
|
for (let tab of this._tabs) {
|
||||||
|
if (!tab.data.itemID) continue;
|
||||||
|
let item = Zotero.Items.get(tab.data.itemID);
|
||||||
|
let title = await item.getTabTitle();
|
||||||
|
this.rename(tab.id, title);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this._unloadInterval = setInterval(() => {
|
this._unloadInterval = setInterval(() => {
|
||||||
this.unloadUnusedTabs();
|
this.unloadUnusedTabs();
|
||||||
}, 60000); // Trigger every minute
|
}, 60000); // Trigger every minute
|
||||||
|
@ -174,6 +187,26 @@ var Zotero_Tabs = new function () {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// When an item is modified, update the title accordingly
|
||||||
|
this.notify = async (event, type, ids, _) => {
|
||||||
|
if (event !== "modify") return;
|
||||||
|
for (let id of ids) {
|
||||||
|
let item = Zotero.Items.get(id);
|
||||||
|
// If a top-level item is updated, update all tabs that have its attachments
|
||||||
|
// Otherwise, just update the tab with the updated attachment
|
||||||
|
let attachmentIDs = item.isAttachment() ? [id] : item.getAttachments();
|
||||||
|
for (let attachmentID of attachmentIDs) {
|
||||||
|
let attachment = Zotero.Items.get(attachmentID);
|
||||||
|
let relevantTabs = this._tabs.filter(tab => tab.data.itemID == attachmentID);
|
||||||
|
if (!relevantTabs.length) continue;
|
||||||
|
for (let tab of relevantTabs) {
|
||||||
|
let title = await attachment.getTabTitle();
|
||||||
|
this.rename(tab.id, title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
this.getState = function () {
|
this.getState = function () {
|
||||||
return this._tabs.map((tab) => {
|
return this._tabs.map((tab) => {
|
||||||
let type = tab.type;
|
let type = tab.type;
|
||||||
|
@ -263,6 +296,16 @@ var Zotero_Tabs = new function () {
|
||||||
this._prevSelectedID = previousID;
|
this._prevSelectedID = previousID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// When a new tab is opened synchronously by ReaderTab constructor, the title is empty.
|
||||||
|
// However, { id, container } needs to return immediately, so do not wait for the new title
|
||||||
|
// and construct it in async manner below.
|
||||||
|
if (!title && data.itemID) {
|
||||||
|
(async () => {
|
||||||
|
let item = Zotero.Items.get(data.itemID);
|
||||||
|
title = await item.getTabTitle();
|
||||||
|
this.rename(tab.id, title);
|
||||||
|
})();
|
||||||
|
}
|
||||||
return { id, container };
|
return { id, container };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -992,6 +992,58 @@ Zotero.Item.prototype.updateDisplayTitle = function () {
|
||||||
this._displayTitle = title;
|
this._displayTitle = title;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get title for the reader tab of a given item accounting for "Show tabs as" pref
|
||||||
|
* @param {Number} itemID - itemID of the attachment
|
||||||
|
* @returns {String} title for the tab of this item
|
||||||
|
*/
|
||||||
|
Zotero.Item.prototype.getTabTitle = async function () {
|
||||||
|
if (!this.isAttachment()) {
|
||||||
|
throw new Error("Can only get tab title for attachments");
|
||||||
|
}
|
||||||
|
let type = Zotero.Prefs.get('tabs.title.reader');
|
||||||
|
let readerTitle = this.getDisplayTitle();
|
||||||
|
let parentItem = this.parentItem;
|
||||||
|
if (type === 'filename') {
|
||||||
|
readerTitle = this.attachmentFilename;
|
||||||
|
}
|
||||||
|
else if (parentItem) {
|
||||||
|
let attachment = await parentItem.getBestAttachment();
|
||||||
|
let isPrimaryAttachment = attachment && attachment.id == this.id;
|
||||||
|
|
||||||
|
let parts = [];
|
||||||
|
// Windows displays bidi control characters as placeholders in window titles, so strip them
|
||||||
|
// See https://github.com/mozilla-services/screenshots/issues/4863
|
||||||
|
let unformatted = Zotero.isWin;
|
||||||
|
let creator = parentItem.getField('firstCreator', unformatted);
|
||||||
|
let year = parentItem.getField('year');
|
||||||
|
if (year == '0000') {
|
||||||
|
year = '';
|
||||||
|
}
|
||||||
|
// Only include parent title if primary attachment
|
||||||
|
let title = isPrimaryAttachment ? parentItem.getDisplayTitle() : false;
|
||||||
|
// If creator is missing fall back to titleCreatorYear
|
||||||
|
if (type === 'creatorYearTitle' && creator) {
|
||||||
|
parts = [creator, year, title];
|
||||||
|
}
|
||||||
|
else if (type === 'title') {
|
||||||
|
parts = [title];
|
||||||
|
}
|
||||||
|
// If type is titleCreatorYear, or is missing, or another type falls back
|
||||||
|
else {
|
||||||
|
parts = [title, creator, year];
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not primary attachment, show attachment title first
|
||||||
|
if (!isPrimaryAttachment) {
|
||||||
|
parts.unshift(this.getDisplayTitle());
|
||||||
|
}
|
||||||
|
|
||||||
|
readerTitle = parts.filter(Boolean).join(' - ');
|
||||||
|
}
|
||||||
|
return readerTitle;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the number of creators for this item
|
* Returns the number of creators for this item
|
||||||
|
|
|
@ -593,49 +593,8 @@ class ReaderInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateTitle() {
|
async updateTitle() {
|
||||||
let type = Zotero.Prefs.get('tabs.title.reader');
|
this._title = await this._item.getTabTitle();
|
||||||
let item = Zotero.Items.get(this._item.id);
|
this._setTitleValue(this._title);
|
||||||
let readerTitle = item.getDisplayTitle();
|
|
||||||
let parentItem = item.parentItem;
|
|
||||||
if (type === 'filename') {
|
|
||||||
readerTitle = item.attachmentFilename;
|
|
||||||
}
|
|
||||||
else if (parentItem) {
|
|
||||||
let attachment = await parentItem.getBestAttachment();
|
|
||||||
let isPrimaryAttachment = attachment && attachment.id == item.id;
|
|
||||||
|
|
||||||
let parts = [];
|
|
||||||
// Windows displays bidi control characters as placeholders in window titles, so strip them
|
|
||||||
// See https://github.com/mozilla-services/screenshots/issues/4863
|
|
||||||
let unformatted = Zotero.isWin;
|
|
||||||
let creator = parentItem.getField('firstCreator', unformatted);
|
|
||||||
let year = parentItem.getField('year');
|
|
||||||
if (year == '0000') {
|
|
||||||
year = '';
|
|
||||||
}
|
|
||||||
// Only include parent title if primary attachment
|
|
||||||
let title = isPrimaryAttachment ? parentItem.getDisplayTitle() : false;
|
|
||||||
// If creator is missing fall back to titleCreatorYear
|
|
||||||
if (type === 'creatorYearTitle' && creator) {
|
|
||||||
parts = [creator, year, title];
|
|
||||||
}
|
|
||||||
else if (type === 'title') {
|
|
||||||
parts = [title];
|
|
||||||
}
|
|
||||||
// If type is titleCreatorYear, or is missing, or another type falls back
|
|
||||||
else {
|
|
||||||
parts = [title, creator, year];
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not primary attachment, show attachment title first
|
|
||||||
if (!isPrimaryAttachment) {
|
|
||||||
parts.unshift(item.getDisplayTitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
readerTitle = parts.filter(Boolean).join(' - ');
|
|
||||||
}
|
|
||||||
this._title = readerTitle;
|
|
||||||
this._setTitleValue(readerTitle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async setAnnotations(items) {
|
async setAnnotations(items) {
|
||||||
|
@ -1360,9 +1319,7 @@ class ReaderTab extends ReaderInstance {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_setTitleValue(title) {
|
_setTitleValue() {}
|
||||||
this._window.Zotero_Tabs.rename(this.tabID, title);
|
|
||||||
}
|
|
||||||
|
|
||||||
_addToNote(annotations) {
|
_addToNote(annotations) {
|
||||||
annotations = annotations.map(x => ({ ...x, attachmentItemID: this._item.id }));
|
annotations = annotations.map(x => ({ ...x, attachmentItemID: this._item.id }));
|
||||||
|
|
Loading…
Reference in a new issue