Improve the new UI:
- Revert `notesList` to standalone notes mode only - Fix splitter styling on Windows - Fix `contextPane` performance fixes - Add a customizable throttle function to `Zotero.Utilities` - Fix reader tab selection issues - Improve error handling in the new editor - Update pdf-reader and zotero-note-editor submodules - Fix contextPane child notes list - Properly notify editor about new images - Fix note title and body snippet extraction - Persist right-hand pane state when switching tab - Hopefully fix two panes visible at the same time
This commit is contained in:
parent
c6a196b999
commit
51f760fe1a
12 changed files with 211 additions and 141 deletions
|
@ -61,7 +61,9 @@
|
|||
|
||||
#zotero-collections-splitter:not([state=collapsed]),
|
||||
#zotero-items-splitter:not([state=collapsed]),
|
||||
#zotero-tags-splitter:not([state=collapsed]) {
|
||||
#zotero-tags-splitter:not([state=collapsed]),
|
||||
#zotero-context-splitter:not([state=collapsed]),
|
||||
#zotero-context-splitter-stacked:not([state=collapsed]) {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
position: relative;
|
||||
|
@ -70,9 +72,15 @@
|
|||
z-index: 1;
|
||||
}
|
||||
|
||||
#zotero-context-splitter:not([state=collapsed]),
|
||||
#zotero-context-splitter-stacked:not([state=collapsed]) {
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter:not([state=collapsed]),
|
||||
#zotero-items-splitter:not([state=collapsed]):not([orient=vertical]),
|
||||
#zotero-tags-splitter:not([state=collapsed]) {
|
||||
#zotero-tags-splitter:not([state=collapsed]),
|
||||
#zotero-context-splitter:not([state=collapsed]) {
|
||||
border-inline-end: 1px solid var(--theme-border-color);
|
||||
min-width: 0;
|
||||
width: 3px;
|
||||
|
@ -80,7 +88,8 @@
|
|||
}
|
||||
|
||||
#zotero-tags-splitter:not([state=collapsed]),
|
||||
#zotero-items-splitter:not([state=collapsed])[orient=vertical] {
|
||||
#zotero-items-splitter:not([state=collapsed])[orient=vertical],
|
||||
#zotero-context-splitter-stacked:not([state=collapsed]) {
|
||||
border-block-end: 1px solid var(--theme-border-color);
|
||||
min-height: 0;
|
||||
height: 3px;
|
||||
|
@ -89,13 +98,16 @@
|
|||
|
||||
#zotero-collections-splitter > grippy,
|
||||
#zotero-items-splitter > grippy,
|
||||
#zotero-tags-splitter > grippy {
|
||||
#zotero-tags-splitter > grippy,
|
||||
#zotero-context-splitter > grippy {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#zotero-collections-splitter:not([state=collapsed]) > grippy,
|
||||
#zotero-items-splitter:not([state=collapsed]) > grippy,
|
||||
#zotero-tags-splitter:not([state=collapsed]) > grippy {
|
||||
#zotero-tags-splitter:not([state=collapsed]) > grippy,
|
||||
#zotero-context-splitter:not([state=collapsed]) > grippy,
|
||||
#zotero-context-splitter-stacked:not([state=collapsed]) > grippy {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,18 +109,8 @@
|
|||
}
|
||||
|
||||
this.notify = async (event, type, ids, extraData) => {
|
||||
// Update citations
|
||||
let uris = [];
|
||||
let items = await Zotero.Items.getAsync(ids);
|
||||
for (let item of items) {
|
||||
let uri = Zotero.URI.getItemURI(item);
|
||||
if (uri) {
|
||||
uris.push(uri)
|
||||
}
|
||||
}
|
||||
|
||||
if (this._editorInstance) {
|
||||
await this._editorInstance.updateCitationsForURIs(uris);
|
||||
await this._editorInstance.notify(ids);
|
||||
}
|
||||
|
||||
if (!this.item) return;
|
||||
|
@ -252,15 +242,14 @@
|
|||
<property name="linksOnTop">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
return;
|
||||
if (val) {
|
||||
var container = this._id('links-container');
|
||||
var parent = container.parentNode;
|
||||
var sib = container.nextSibling;
|
||||
while (parent.firstChild !== container) {
|
||||
parent.insertBefore(parent.removeChild(parent.firstChild), sib);
|
||||
}
|
||||
}
|
||||
// if (val) {
|
||||
// var container = this._id('links-container');
|
||||
// var parent = container.parentNode;
|
||||
// var sib = container.nextSibling;
|
||||
// while (parent.firstChild !== container) {
|
||||
// parent.insertBefore(parent.removeChild(parent.firstChild), sib);
|
||||
// }
|
||||
// }
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
|
|
@ -25,18 +25,14 @@
|
|||
|
||||
import React, { forwardRef, useImperativeHandle, useState } from 'react';
|
||||
|
||||
const NoteRow = ({ parentTitle, parentImageSrc, title, body, date, onClick }) => {
|
||||
const NoteRow = ({ title, body, date, onClick }) => {
|
||||
return (
|
||||
<div className="note-row" onClick={onClick}>
|
||||
<div className="inner">
|
||||
{parentTitle !== null && <div className="first-line">
|
||||
<div className="icon"><img src={parentImageSrc}/></div>
|
||||
<div className="title">{parentTitle}</div>
|
||||
</div>}
|
||||
<div className="second-line">
|
||||
<div className="first-line">
|
||||
<div className="title">{title}</div>
|
||||
</div>
|
||||
<div className="third-line">
|
||||
<div className="second-line">
|
||||
<div className="date">{date}</div>
|
||||
<div className="body">{body}</div>
|
||||
</div>
|
||||
|
|
|
@ -82,43 +82,66 @@ var ZoteroContextPane = new function () {
|
|||
|
||||
_init();
|
||||
|
||||
this._unregisterID = Zotero.Notifier.registerObserver(this, ['item', 'tab'], 'contextPane');
|
||||
this._notifierID = Zotero.Notifier.registerObserver(this, ['item', 'tab'], 'contextPane');
|
||||
window.addEventListener('resize', _update);
|
||||
_itemToggle.addEventListener('click', () => {
|
||||
_togglePane(0);
|
||||
});
|
||||
_notesToggle.addEventListener('click', () => {
|
||||
_togglePane(1);
|
||||
});
|
||||
_itemToggle.addEventListener('click', _toggleItemButton);
|
||||
_notesToggle.addEventListener('click', _toggleNotesButton);
|
||||
Zotero.Reader.onChangeSidebarWidth = _updatePaneWidth;
|
||||
Zotero.Reader.onChangeSidebarOpen = _updatePaneWidth;
|
||||
|
||||
const observer = new MutationObserver(() => {
|
||||
this._mutationObserver = new MutationObserver(() => {
|
||||
_updateToolbarWidth();
|
||||
// Sometimes XUL is late to reflow
|
||||
setTimeout(_updateToolbarWidth, 100);
|
||||
});
|
||||
observer.observe(_tabToolbarContainer, { attributes: true, childList: true, subtree: true });
|
||||
this._mutationObserver.observe(_tabToolbarContainer, { attributes: true, childList: true, subtree: true });
|
||||
};
|
||||
|
||||
this.onUnload = function () {
|
||||
Zotero.Notifier.unregisterObserver(this._unregisterID);
|
||||
_itemToggle.removeEventListener('click', _toggleItemButton);
|
||||
_notesToggle.removeEventListener('click', _toggleNotesButton);
|
||||
window.removeEventListener('resize', _update);
|
||||
Zotero.Notifier.unregisterObserver(this._notifierID);
|
||||
this._mutationObserver.disconnect();
|
||||
Zotero.Reader.onChangeSidebarWidth = () => {};
|
||||
Zotero.Reader.onChangeSidebarOpen = () => {};
|
||||
_contextPaneInner.innerHTML = '';
|
||||
_itemContexts = [];
|
||||
_notesContexts = [];
|
||||
};
|
||||
|
||||
this.notify = Zotero.Promise.coroutine(function* (action, type, ids, extraData) {
|
||||
if (type == 'item') {
|
||||
// TODO: Filter library and seriously thing about the performance of this part
|
||||
for (let context of _itemContexts) {
|
||||
// Update, remove or re-create item panes
|
||||
for (let context of _itemContexts.slice()) {
|
||||
let item = Zotero.Items.get(context.itemID);
|
||||
if (item && item.parentID != context.parentID) {
|
||||
if (!item) {
|
||||
_removeItemContext(context.tabID);
|
||||
}
|
||||
else if (item.parentID != context.parentID) {
|
||||
_removeItemContext(context.tabID);
|
||||
_addItemContext(context.tabID, context.itemID);
|
||||
}
|
||||
context.update();
|
||||
else {
|
||||
context.update();
|
||||
}
|
||||
}
|
||||
|
||||
// Update notes lists for affected libraries
|
||||
let libraryIDs = [];
|
||||
for (let id of ids) {
|
||||
let item = Zotero.Items.get(id);
|
||||
if (item && item.isNote()) {
|
||||
libraryIDs.push(item.libraryID);
|
||||
}
|
||||
else if (action == 'delete') {
|
||||
libraryIDs.push(extraData[id].libraryID);
|
||||
}
|
||||
}
|
||||
for (let context of _notesContexts) {
|
||||
context.updateNotesList();
|
||||
if (libraryIDs.includes(context.libraryID)) {
|
||||
context.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == 'tab') {
|
||||
|
@ -157,11 +180,19 @@ var ZoteroContextPane = new function () {
|
|||
if (context) {
|
||||
_selectNotesContext(context.libraryID);
|
||||
}
|
||||
_selectItemContext(ids[0], extraData[ids[0]].type);
|
||||
_selectItemContext(ids[0]);
|
||||
_update();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function _toggleItemButton() {
|
||||
_togglePane(0);
|
||||
}
|
||||
|
||||
function _toggleNotesButton() {
|
||||
_togglePane(1);
|
||||
}
|
||||
|
||||
function _removeNote(id) {
|
||||
var ps = Components.classes['@mozilla.org/embedcomp/prompt-service;1']
|
||||
|
@ -183,11 +214,13 @@ var ZoteroContextPane = new function () {
|
|||
if (splitter.getAttribute('state') != 'collapsed') {
|
||||
if (_panesDeck.selectedIndex == 0) {
|
||||
let child = _itemPaneDeck.selectedPanel;
|
||||
var tabPanels = child.querySelector('tabpanels');
|
||||
if (tabPanels && tabPanels.selectedIndex == 1) {
|
||||
var notesDeck = child.querySelector('.notes-deck');
|
||||
if (notesDeck.selectedIndex == 1) {
|
||||
return child.querySelector('zoteronoteeditor');
|
||||
if (child) {
|
||||
var tabPanels = child.querySelector('tabpanels');
|
||||
if (tabPanels && tabPanels.selectedIndex == 1) {
|
||||
var notesDeck = child.querySelector('.notes-deck');
|
||||
if (notesDeck.selectedIndex == 1) {
|
||||
return child.querySelector('zoteronoteeditor');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -286,29 +319,18 @@ var ZoteroContextPane = new function () {
|
|||
}
|
||||
|
||||
function _togglePane(paneIndex) {
|
||||
var splitter;
|
||||
var stacked = Zotero.Prefs.get('layout') == 'stacked';
|
||||
if (stacked) {
|
||||
splitter = _contextPaneSplitterStacked;
|
||||
}
|
||||
else {
|
||||
splitter = _contextPaneSplitter;
|
||||
}
|
||||
var splitter = Zotero.Prefs.get('layout') == 'stacked'
|
||||
? _contextPaneSplitterStacked : _contextPaneSplitter;
|
||||
|
||||
var isOpen = splitter.getAttribute('state') != 'collapsed';
|
||||
var hide = false;
|
||||
|
||||
var currentPane = _panesDeck.selectedIndex;
|
||||
|
||||
if (isOpen && currentPane == paneIndex) {
|
||||
hide = true;
|
||||
}
|
||||
else {
|
||||
_panesDeck.setAttribute('selectedIndex', paneIndex);
|
||||
}
|
||||
|
||||
var context = _itemContexts.find(x => x.tabID == Zotero_Tabs.selectedID);
|
||||
context.selectedIndex = paneIndex;
|
||||
|
||||
splitter.setAttribute('state', hide ? 'collapsed' : 'open');
|
||||
_update();
|
||||
|
@ -371,7 +393,7 @@ var ZoteroContextPane = new function () {
|
|||
|
||||
var label = document.createElement('label');
|
||||
var button = document.createElement('button');
|
||||
button.setAttribute('label', Zotero.Intl.strings['zotero.item.add']);
|
||||
button.setAttribute('label', Zotero.Intl.strings['zotero.toolbar.newNote']);
|
||||
button.addEventListener('click', () => {
|
||||
contextNode.setAttribute('selectedIndex', 1);
|
||||
var item = new Zotero.Item('note');
|
||||
|
@ -394,7 +416,7 @@ var ZoteroContextPane = new function () {
|
|||
input.setAttribute('type', 'search');
|
||||
input.setAttribute('timeout', '250');
|
||||
input.addEventListener('command', () => {
|
||||
updateNotesList();
|
||||
_updateNotesList();
|
||||
});
|
||||
vbox2.append(input);
|
||||
|
||||
|
@ -411,20 +433,20 @@ var ZoteroContextPane = new function () {
|
|||
|
||||
var notesListRef = React.createRef();
|
||||
|
||||
var updateNotesList = async (reset) => {
|
||||
async function _updateNotesList(reset) {
|
||||
if (reset) {
|
||||
input.value = '';
|
||||
contextNode.setAttribute('selectedIndex', 0);
|
||||
}
|
||||
var text = input.value;
|
||||
var query = input.value;
|
||||
|
||||
await Zotero.Schema.schemaUpdatePromise;
|
||||
var s = new Zotero.Search();
|
||||
s.addCondition('libraryID', 'is', libraryID);
|
||||
s.addCondition('itemType', 'is', 'note');
|
||||
s.addCondition('noChildren', 'false');
|
||||
if (text) {
|
||||
s.addCondition('note', 'contains', text, true);
|
||||
s.addCondition('noChildren', 'true');
|
||||
if (query) {
|
||||
s.addCondition('note', 'contains', query, true);
|
||||
}
|
||||
var notes = await s.search();
|
||||
notes = Zotero.Items.get(notes);
|
||||
|
@ -435,20 +457,15 @@ var ZoteroContextPane = new function () {
|
|||
});
|
||||
|
||||
notesListRef.current.setNotes(notes.map(note => {
|
||||
var text2 = note.note.slice(0, 500);
|
||||
text2 = text2.trim();
|
||||
// TODO: Fix a potential performance issuse
|
||||
text2 = Zotero.Utilities.unescapeHTML(text2);
|
||||
var parts = text2.split('\n').map(x => x.trim()).filter(x => x.length);
|
||||
var parent = null;
|
||||
if (note.parentID) {
|
||||
parent = Zotero.Items.get(note.parentID);
|
||||
}
|
||||
var text = note.note;
|
||||
text = Zotero.Utilities.unescapeHTML(text);
|
||||
text = text.trim();
|
||||
text = text.slice(0, 500);
|
||||
var parts = text.split('\n').map(x => x.trim()).filter(x => x.length);
|
||||
var title = parts[0] && parts[0].slice(0, Zotero.Notes.MAX_TITLE_LENGTH);
|
||||
return {
|
||||
id: note.id,
|
||||
parentTitle: parent && parent.getDisplayTitle(),
|
||||
parentImageSrc: parent && parent.getImageSrc(),
|
||||
title: parts[0] || Zotero.getString('pane.item.notes.untitled'),
|
||||
title: title || Zotero.getString('pane.item.notes.untitled'),
|
||||
body: parts[1] || '',
|
||||
date: (new Date(note.dateModified).toLocaleDateString(Zotero.locale))
|
||||
};
|
||||
|
@ -468,14 +485,14 @@ var ZoteroContextPane = new function () {
|
|||
/>,
|
||||
listInner,
|
||||
() => {
|
||||
updateNotesList();
|
||||
_updateNotesList();
|
||||
}
|
||||
);
|
||||
|
||||
var context = {
|
||||
libraryID,
|
||||
node: contextNode,
|
||||
updateNotesList,
|
||||
update: Zotero.Utilities.throttle(_updateNotesList, 1000, { leading: false }),
|
||||
editor
|
||||
};
|
||||
|
||||
|
@ -503,7 +520,7 @@ var ZoteroContextPane = new function () {
|
|||
_notesContexts = _notesContexts.filter(x => x.libraryID != libraryID);
|
||||
}
|
||||
|
||||
function _libraryEditable(libraryID) {
|
||||
function _isLibraryEditable(libraryID) {
|
||||
var type = Zotero.Libraries.get(libraryID).libraryType;
|
||||
if (type == 'group') {
|
||||
var groupID = Zotero.Groups.getGroupIDFromLibraryID(libraryID);
|
||||
|
@ -514,7 +531,7 @@ var ZoteroContextPane = new function () {
|
|||
}
|
||||
|
||||
function _setPinnedNote(libraryID, itemID) {
|
||||
var editable = _libraryEditable(libraryID);
|
||||
var editable = _isLibraryEditable(libraryID);
|
||||
var context = _getNotesContext(libraryID);
|
||||
if (context) {
|
||||
let { editor, node } = context;
|
||||
|
@ -530,7 +547,7 @@ var ZoteroContextPane = new function () {
|
|||
function _appendNoteRows(notes, list, editable, onClick, onDelete) {
|
||||
for (var i = 0; i < notes.length; i++) {
|
||||
var note = notes[i];
|
||||
var id = notes[i].id;
|
||||
let id = notes[i].id;
|
||||
|
||||
var icon = document.createElement('image');
|
||||
icon.className = 'zotero-box-icon';
|
||||
|
@ -551,7 +568,9 @@ var ZoteroContextPane = new function () {
|
|||
});
|
||||
box.appendChild(icon);
|
||||
box.appendChild(label);
|
||||
|
||||
|
||||
var row = document.createElement('row');
|
||||
row.appendChild(box);
|
||||
if (editable) {
|
||||
var removeButton = document.createElement('label');
|
||||
removeButton.setAttribute('value', '-');
|
||||
|
@ -559,11 +578,6 @@ var ZoteroContextPane = new function () {
|
|||
removeButton.addEventListener('click', function () {
|
||||
onDelete(id);
|
||||
});
|
||||
}
|
||||
|
||||
var row = document.createElement('row');
|
||||
row.appendChild(box);
|
||||
if (editable) {
|
||||
row.appendChild(removeButton);
|
||||
}
|
||||
|
||||
|
@ -576,34 +590,32 @@ var ZoteroContextPane = new function () {
|
|||
_itemContexts = _itemContexts.filter(x => x.tabID != tabID);
|
||||
}
|
||||
|
||||
function _selectItemContext(tabID, type) {
|
||||
function _selectItemContext(tabID) {
|
||||
let selectedIndex = Array.from(_itemPaneDeck.children).findIndex(x => x.id == tabID + '-context');
|
||||
if (selectedIndex != -1) {
|
||||
_itemPaneDeck.setAttribute('selectedIndex', selectedIndex);
|
||||
var context = _itemContexts.find(x => x.tabID == tabID);
|
||||
if (context && Zotero_Tabs.selectedIndex > 0) {
|
||||
_panesDeck.setAttribute('selectedIndex', context.selectedIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _addItemContext(tabID, itemID) {
|
||||
var item = Zotero.Items.get(itemID);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
var libraryID = item.libraryID;
|
||||
var editable = _isLibraryEditable(libraryID);
|
||||
var parentID = item.parentID;
|
||||
|
||||
var container = document.createElement('vbox');
|
||||
container.id = tabID + '-context';
|
||||
container.className = 'zotero-item-pane-content';
|
||||
_itemPaneDeck.appendChild(container);
|
||||
|
||||
var item = Zotero.Items.get(itemID);
|
||||
var libraryID = item.libraryID;
|
||||
var editable = _libraryEditable(libraryID);
|
||||
var parentID = item.parentID;
|
||||
|
||||
var context = {
|
||||
tabID,
|
||||
itemID,
|
||||
parentID,
|
||||
libraryID,
|
||||
selectedIndex: 0,
|
||||
update: () => {}
|
||||
};
|
||||
_itemContexts.push(context);
|
||||
|
@ -619,7 +631,6 @@ var ZoteroContextPane = new function () {
|
|||
container.append(vbox);
|
||||
return;
|
||||
}
|
||||
|
||||
var parentItem = Zotero.Items.get(item.parentID);
|
||||
|
||||
// tabbox
|
||||
|
@ -685,7 +696,6 @@ var ZoteroContextPane = new function () {
|
|||
hbox.setAttribute('align', 'center');
|
||||
var label = document.createElement('label');
|
||||
var button = document.createElement('button');
|
||||
// TODO: Should not depend on the current ZoteroPane state
|
||||
button.hidden = !editable;
|
||||
button.setAttribute('label', Zotero.Intl.strings['zotero.item.add']);
|
||||
button.addEventListener('click', () => {
|
||||
|
@ -763,6 +773,10 @@ var ZoteroContextPane = new function () {
|
|||
|
||||
function _renderNotesPanel() {
|
||||
rows.innerHTML = '';
|
||||
var parentItem = Zotero.Items.get(parentID);
|
||||
if (!parentItem) {
|
||||
return;
|
||||
}
|
||||
var parentNotes = Zotero.Items.get(parentItem.getNotes());
|
||||
_appendNoteRows(parentNotes, rows, editable, (id) => {
|
||||
deck.setAttribute('selectedIndex', 1);
|
||||
|
@ -782,7 +796,7 @@ var ZoteroContextPane = new function () {
|
|||
label.value = Zotero.getString(str, [c]);
|
||||
}
|
||||
|
||||
context.update = _renderNotesPanel;
|
||||
context.update = Zotero.Utilities.throttle(_renderNotesPanel, 500);
|
||||
_renderNotesPanel();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -113,7 +113,7 @@ var Zotero_Tabs = new function () {
|
|||
index = index || this._tabs.length;
|
||||
this._tabs.splice(index, 0, tab);
|
||||
this._update();
|
||||
Zotero.Notifier.trigger('add', 'tab', [id], { [id]: notifierData });
|
||||
Zotero.Notifier.trigger('add', 'tab', [id], { [id]: notifierData }, true);
|
||||
if (select) {
|
||||
this.select(id);
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ var Zotero_Tabs = new function () {
|
|||
if (tab.onClose) {
|
||||
tab.onClose();
|
||||
}
|
||||
Zotero.Notifier.trigger('close', 'tab', [tab.id]);
|
||||
Zotero.Notifier.trigger('close', 'tab', [tab.id], true);
|
||||
this._update();
|
||||
};
|
||||
|
||||
|
@ -199,7 +199,7 @@ var Zotero_Tabs = new function () {
|
|||
this._selectedID = id;
|
||||
this.deck.selectedIndex = Array.from(this.deck.children).findIndex(x => x.id == id);
|
||||
this._update();
|
||||
Zotero.Notifier.trigger('select', 'tab', [tab.id], { [tab.id]: { type: tab.type } });
|
||||
Zotero.Notifier.trigger('select', 'tab', [tab.id], { [tab.id]: { type: tab.type } }, true);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -101,11 +101,28 @@ class EditorInstance {
|
|||
async updateCitationsForURIs(uris) {
|
||||
let subscriptions = this._subscriptions
|
||||
.filter(s => s.data.citation && s.data.citation.citationItems
|
||||
.some(citationItem => uris.some(uri => citationItem.uris.includes(uri))));
|
||||
.some(citationItem => citationItem.uris && uris.some(uri => citationItem.uris.includes(uri))));
|
||||
for (let subscription of subscriptions) {
|
||||
await this._feedSubscription(subscription);
|
||||
}
|
||||
}
|
||||
|
||||
async notify(ids) {
|
||||
let items = await Zotero.Items.getAsync(ids);
|
||||
|
||||
// Update attachments
|
||||
let keys = items.map(item => item.key);
|
||||
this._subscriptions
|
||||
.filter(s => keys.includes(s.data.attachmentKey))
|
||||
.forEach(s => this._feedSubscription(s));
|
||||
|
||||
// Update citations
|
||||
let uris = items.map(x => Zotero.URI.getItemURI(x)).filter(x => x);
|
||||
this._subscriptions
|
||||
.filter(s => s.data.citation && s.data.citation.citationItems
|
||||
.some(citationItem => citationItem.uris && uris.some(uri => citationItem.uris.includes(uri))))
|
||||
.forEach(s => this._feedSubscription(s));
|
||||
}
|
||||
|
||||
saveSync() {
|
||||
if (!this._readOnly && !this._disableSaving && this._iframeWindow) {
|
||||
|
@ -600,6 +617,9 @@ class EditorInstance {
|
|||
async _getFormattedCitationParts(citation) {
|
||||
let formattedItems = [];
|
||||
for (let citationItem of citation.citationItems) {
|
||||
if (!Array.isArray(citationItem.uris)) {
|
||||
continue;
|
||||
}
|
||||
let item = await this._getItemFromURIs(citationItem.uris);
|
||||
if (!item && citationItem.itemData) {
|
||||
item = new Zotero.Item();
|
||||
|
|
|
@ -755,6 +755,10 @@ class Reader {
|
|||
}
|
||||
|
||||
if (reader) {
|
||||
if (reader instanceof ReaderTab) {
|
||||
reader._window.Zotero_Tabs.select(reader.tabID);
|
||||
}
|
||||
|
||||
if (location) {
|
||||
reader.navigate(location);
|
||||
}
|
||||
|
@ -806,9 +810,6 @@ class Reader {
|
|||
if (reader instanceof ReaderWindow) {
|
||||
reader._window.focus();
|
||||
}
|
||||
else {
|
||||
reader._window.Zotero_Tabs.select(reader.tabID);
|
||||
}
|
||||
}
|
||||
|
||||
async triggerAnnotationsImportCheck(itemID) {
|
||||
|
|
|
@ -49,6 +49,62 @@ Zotero.Utilities = {
|
|||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates and returns a new, throttled version of the
|
||||
* passed function, that, when invoked repeatedly,
|
||||
* will only actually call the original function at most
|
||||
* once per every wait milliseconds
|
||||
*
|
||||
* By default, throttle will execute the function as soon
|
||||
* as you call it for the first time, and, if you call it
|
||||
* again any number of times during the wait period, as soon
|
||||
* as that period is over. If you'd like to disable the
|
||||
* leading-edge call, pass {leading: false}, and if you'd
|
||||
* like to disable the execution on the trailing-edge,
|
||||
* pass {trailing: false}. See
|
||||
* https://underscorejs.org/#throttle
|
||||
* https://github.com/jashkenas/underscore/blob/master/underscore.js
|
||||
* (c) 2009-2018 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
* Underscore may be freely distributed under the MIT license.
|
||||
*
|
||||
* @param {Function} func Function to throttle
|
||||
* @param {Integer} wait Wait period in milliseconds
|
||||
* @param {Boolean} [options.leading] Call at the beginning of the wait period
|
||||
* @param {Boolean} [options.trailing] Call at the end of the wait period
|
||||
*/
|
||||
throttle: function (func, wait, options) {
|
||||
var context, args, result;
|
||||
var timeout = null;
|
||||
var previous = 0;
|
||||
if (!options) options = {};
|
||||
var later = function () {
|
||||
previous = options.leading === false ? 0 : Date.now();
|
||||
timeout = null;
|
||||
result = func.apply(context, args);
|
||||
if (!timeout) context = args = null;
|
||||
};
|
||||
return function () {
|
||||
var now = Date.now();
|
||||
if (!previous && options.leading === false) previous = now;
|
||||
var remaining = wait - (now - previous);
|
||||
context = this;
|
||||
args = arguments;
|
||||
if (remaining <= 0 || remaining > wait) {
|
||||
if (timeout) {
|
||||
clearTimeout(timeout);
|
||||
timeout = null;
|
||||
}
|
||||
previous = now;
|
||||
result = func.apply(context, args);
|
||||
if (!timeout) context = args = null;
|
||||
}
|
||||
else if (!timeout && options.trailing !== false) {
|
||||
timeout = setTimeout(later, remaining);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Fixes author name capitalization.
|
||||
* Currently for all uppercase names only
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
}
|
||||
|
||||
#zotero-context-pane {
|
||||
min-width: 300px;
|
||||
min-width: 360px;
|
||||
}
|
||||
|
||||
#zotero-context-pane.stacked {
|
||||
|
@ -49,7 +49,7 @@
|
|||
right: 0;
|
||||
height: 32px;
|
||||
-moz-appearance: none;
|
||||
background: linear-gradient(to top, #aeaeae 0, #aeaeae 1px, #d3d3d3 1px, #e3e3e3 100%);
|
||||
background: linear-gradient(to top, #a9a9a9 0, #a9a9a9 1px, #f6f6f6 1px, #f6f6f6 100%);
|
||||
}
|
||||
|
||||
#zotero-tab-toolbar-container #zotero-tb-locate,
|
||||
|
@ -63,7 +63,7 @@
|
|||
opacity: 0.99;
|
||||
width: 100%;
|
||||
margin-inline-start: -5px;
|
||||
background: linear-gradient(to top, #aeaeae 0, #aeaeae 1px, #d3d3d3 1px, #e3e3e3 100%);
|
||||
background: linear-gradient(to top, #a9a9a9 0, #a9a9a9 1px, #f6f6f6 1px, #f6f6f6 100%);
|
||||
}
|
||||
|
||||
.zotero-context-notes-list {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit be1fa9a77fb9090a1aad9a9cd40b8ebb22ee4281
|
||||
Subproject commit 7595b7d83720941812a531b9a547deac626b24bc
|
|
@ -31,24 +31,6 @@
|
|||
.first-line {
|
||||
display: flex;
|
||||
|
||||
.icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
flex-grow: 1;
|
||||
width: 0;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.second-line {
|
||||
display: flex;
|
||||
|
||||
.title {
|
||||
flex-grow: 1;
|
||||
width: 0;
|
||||
|
@ -59,7 +41,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.third-line {
|
||||
.second-line {
|
||||
display: flex;
|
||||
|
||||
.date {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit a271598218fa8f52cd6d571d5c1b28e913803409
|
||||
Subproject commit db2bfc6cbb724dbb1a22bafc324357a1bd61c3b1
|
Loading…
Reference in a new issue