From 8709ddd65728044bbf3f124d3aaf9b1c63bc7782 Mon Sep 17 00:00:00 2001 From: Martynas Bagdonas Date: Mon, 5 Oct 2020 10:00:17 +0300 Subject: [PATCH] Experiment with the new UI --- chrome/content/zotero/bindings/noteeditor.xml | 15 +- chrome/content/zotero/itemPane.js | 403 +++++++++++++++++- chrome/content/zotero/itemPane.xul | 226 +++++----- chrome/content/zotero/tabs.js | 8 +- chrome/content/zotero/xpcom/data/notes.js | 8 +- chrome/content/zotero/xpcom/editorInstance.js | 134 ++++-- chrome/content/zotero/xpcom/notifier.js | 2 +- chrome/content/zotero/xpcom/reader.js | 58 ++- chrome/content/zotero/zoteroPane.js | 13 +- chrome/content/zotero/zoteroPane.xul | 10 +- pdf-reader | 2 +- pdf-worker | 2 +- zotero-note-editor | 2 +- 13 files changed, 692 insertions(+), 191 deletions(-) diff --git a/chrome/content/zotero/bindings/noteeditor.xml b/chrome/content/zotero/bindings/noteeditor.xml index 07ed3e6ef5..f6ca7f0d74 100644 --- a/chrome/content/zotero/bindings/noteeditor.xml +++ b/chrome/content/zotero/bindings/noteeditor.xml @@ -82,6 +82,10 @@ this._editorInstance.saveSync(); } } + + this.getCurrentInstance = () => { + return this._editorInstance; + } this.initEditor = async (state) => { if (this._editorInstance) { @@ -94,7 +98,8 @@ iframeWindow: document.getAnonymousElementByAttribute(this, 'anonid', 'editor-view').contentWindow, popup: document.getAnonymousElementByAttribute(this, 'anonid', 'editor-menu'), onNavigate: this._navigateHandler, - readOnly: !this.editable + readOnly: !this.editable, + placeholder: this.placeholder }); } @@ -220,10 +225,10 @@ this.initEditor(); - var parentKey = this._item.parentKey; - if (parentKey) { - this.parentItem = Zotero.Items.getByLibraryAndKey(this._item.libraryID, parentKey); - } + // var parentKey = this._item.parentKey; + // if (parentKey) { + // this.parentItem = Zotero.Items.getByLibraryAndKey(this._item.libraryID, parentKey); + // } this._id('links-box').item = this._item; })(); diff --git a/chrome/content/zotero/itemPane.js b/chrome/content/zotero/itemPane.js index 33a7f11d88..24bd79b9fb 100644 --- a/chrome/content/zotero/itemPane.js +++ b/chrome/content/zotero/itemPane.js @@ -32,6 +32,7 @@ var ZoteroItemPane = new function() { var _selectedNoteID; var _translationTarget; var _noteIDs; + var _recentlyPinned = []; this.onLoad = function () { if (!Zotero) { @@ -55,7 +56,15 @@ var ZoteroItemPane = new function() { }; _relatedBox = document.getElementById('zotero-editpane-related'); - this._unregisterID = Zotero.Notifier.registerObserver(this, ['item'], 'itemPane'); + this._unregisterID = Zotero.Notifier.registerObserver(this, ['item', 'tab'], 'itemPane'); + + document.getElementById('temp-toggle-1').addEventListener('click', () => { + this.togglePane(); + }); + document.getElementById('temp-toggle-2').addEventListener('click', () => { + this.togglePane(); + }); + this.initPinnedView(); } @@ -213,15 +222,28 @@ var ZoteroItemPane = new function() { this.notify = Zotero.Promise.coroutine(function* (action, type, ids, extraData) { - var viewBox = document.getElementById('zotero-view-item'); - // If notes pane is selected, refresh it if any of the notes change or are deleted - if (viewBox.selectedIndex == 1 && (action == 'modify' || action == 'delete')) { - let refresh = false; - if (ids.some(id => _noteIDs.has(id))) { - refresh = true; + if(type == 'item') { + var viewBox = document.getElementById('zotero-view-item'); + // If notes pane is selected, refresh it if any of the notes change or are deleted + if (viewBox.selectedIndex == 1 && (action == 'modify' || action == 'delete')) { + let refresh = false; + if (ids.some(id => _noteIDs.has(id))) { + refresh = true; + } + if (refresh) { + yield this.viewItem(_lastItem, null, 1); + } } - if (refresh) { - yield this.viewItem(_lastItem, null, 1); + } + else if (type == 'tab') { + if (action == 'add') { + this.addPDFTabContext(ids[0], extraData.itemID); + } + else if (action == 'close') { + this.removeTabContext(ids[0]); + } + else if (action == 'select') { + this.selectTabContext(ids[0], extraData.type); } } }); @@ -435,6 +457,369 @@ var ZoteroItemPane = new function() { elem.setAttribute('tooltiptext', tooltip); }; + this.getActiveNote = function() { + let mainDeck = document.getElementById('zotero-item-pane-main-deck'); + if (mainDeck.selectedIndex == 0) { + let contextualDeck = document.getElementById('zotero-item-pane-contextual-deck'); + if (contextualDeck.selectedIndex > 0) { + let child = contextualDeck.children[contextualDeck.selectedIndex]; + if (child.querySelector('deck').selectedIndex == 1) { + return child.querySelector('zoteronoteeditor'); + } + } + } + else { + let pinnedDeck = document.getElementById('zotero-item-pane-pin-deck2'); + if (pinnedDeck.selectedIndex == 1) { + return pinnedDeck.querySelector('zoteronoteeditor'); + } + } + return null; + } + + window.addEventListener('mousedown', () => { + Zotero.debug('active note') + Zotero.debug(this.getActiveNote()) + }); + + this.pinNote = function(itemID) { + _recentlyPinned.unshift(itemID); + _recentlyPinned = _recentlyPinned.slice(0, 10); + this._setPinnedNote(itemID); + this._updatePinnedList(); + } + + this.togglePane = function(forceItem) { + let mainDeck = document.getElementById('zotero-item-pane-main-deck'); + let value; + if (forceItem !== undefined) { + value = forceItem ? 0 : 1; + } + else { + value = mainDeck.selectedIndex == 0 ? 1 : 0; + } + + document.getElementById('temp-toggle-1').firstChild.remove(); + document.getElementById('temp-toggle-2').firstChild.remove(); + if (value == 0) { + document.getElementById('temp-toggle-1').append('(Slider)__________'); + document.getElementById('temp-toggle-2').append('(Slider)__________'); + } + else { + document.getElementById('temp-toggle-1').append('__________(Slider)'); + document.getElementById('temp-toggle-2').append('__________(Slider)'); + } + + mainDeck.selectedIndex = value; + } + + this.initPinnedView = async function () { + + + let container = document.getElementById('zotero-item-pane-pin-deck'); + + let bar = document.createElement('hbox'); + container.appendChild(bar); + let inner = document.createElement('deck'); + inner.id = 'zotero-item-pane-pin-deck2'; + inner.style.backgroundColor = 'white'; + inner.setAttribute('flex', 1); + container.appendChild(inner); + + let returnButton = document.createElement('toolbarbutton'); + returnButton.className = 'zotero-tb-button'; + returnButton.id = 'zotero-tb-return'; + returnButton.style.listStyleImage = "url('chrome://zotero/skin/citation-delete.png')" + returnButton.addEventListener('click', () => { + inner.setAttribute('selectedIndex', 0); + }); + + + bar.append(returnButton, 'Pinned note'); + bar.style.overflowX = 'hidden'; + bar.style.textOverflow = 'ellipsis'; + bar.style.fontWeight = 'bold'; + + + + let list = document.createElement('vbox'); + list.setAttribute('flex', 1); + list.className = 'zotero-box'; + + + + + let note = document.createElement('zoteronoteeditor'); + note.id = 'zotero-item-pane-pinned-note'; + note.setAttribute('flex', 1); + inner.appendChild(list); + inner.appendChild(note); + + inner.setAttribute('selectedIndex', 0); + + + let head = document.createElement('hbox'); + head.setAttribute('align', 'center'); + let label = document.createElement('label'); + let button = document.createElement('button'); + button.setAttribute('label', 'Add'); + button.addEventListener('click', async () => { + inner.setAttribute('selectedIndex', 1); + let item = new Zotero.Item('note'); + item.libraryID = parentItem.libraryID; + item.parentKey = parentItem.key; + note.mode = 'edit'; + note.item = item; + note.parentItem = null; + }); + head.append(label, button); + + let grid = document.createElement('grid'); + grid.setAttribute('flex', 1); + grid.style.overflowY = 'scroll'; + let columns = document.createElement('columns'); + let column1 = document.createElement('column'); + column1.setAttribute('flex', 1); + let column2 = document.createElement('column'); + columns.append(column1, column2); + grid.append(columns); + let rows = document.createElement('rows'); + rows.setAttribute('flex', 1); + rows.id = 'zotero-item-pane-pinned-list'; + grid.append(rows); + + list.append(head, grid); + + this._updatePinnedList(); + } + + this._updatePinnedList = async function() { + let rows = document.getElementById('zotero-item-pane-pinned-list'); + while (rows.hasChildNodes()) { + rows.removeChild(rows.firstChild); + } + + await Zotero.Schema.schemaUpdatePromise; + var s = new Zotero.Search(); + s.addCondition('libraryID', 'is', 1); + s.addCondition('itemType', 'is', 'note'); + s.addCondition('noChildren', 'true'); + let notes = await s.search(); + notes = Zotero.Items.get(notes); + notes.sort((a, b) => { + a = a.getField('dateModified'); + b = b.getField('dateModified'); + return b.localeCompare(a); + }); + + var row = document.createElement('row'); + row.style.fontWeight = 'bold'; + row.appendChild(document.createTextNode('Recently pinned notes')); + rows.append(row); + this._appendNoteRows(Zotero.Items.get(_recentlyPinned), rows, false, (id) => { + this._setPinnedNote(id); + }); + + row = document.createElement('row'); + row.style.fontWeight = 'bold'; + row.appendChild(document.createTextNode('Recently edited standalone notes')); + rows.append(row); + + this._appendNoteRows(notes, rows, false, (id) => { + this._setPinnedNote(id); + }); + } + + this._setPinnedNote = function (itemID) { + let pinnedDeck = document.getElementById('zotero-item-pane-pin-deck2'); + pinnedDeck.setAttribute('selectedIndex', 1); + let pinnedNote = document.getElementById('zotero-item-pane-pinned-note'); + pinnedNote.mode = 'edit'; + pinnedNote.item = Zotero.Items.get(itemID); + pinnedNote.parentItem = null; + this.togglePane(false); + } + + this._appendNoteRows = function (notes, list, editable, onClick, onDelete) { + for (var i = 0; i < notes.length; i++) { + let note = notes[i]; + let id = notes[i].id; + + var icon = document.createElement('image'); + icon.className = 'zotero-box-icon'; + icon.setAttribute('src', `chrome://zotero/skin/treeitem-note${Zotero.hiDPISuffix}.png`); + + var label = document.createElement('label'); + label.className = 'zotero-box-label'; + var title = note.getNoteTitle(); + title = title ? title : Zotero.getString('pane.item.notes.untitled'); + label.setAttribute('value', title); + label.setAttribute('flex', '1'); //so that the long names will flex smaller + label.setAttribute('crop', 'end'); + + var box = document.createElement('box'); + box.setAttribute('class', 'zotero-clicky'); + box.addEventListener('click', () => { + onClick(id); + }); + box.appendChild(icon); + box.appendChild(label); + + if (editable) { + var removeButton = document.createElement('label'); + removeButton.setAttribute('value', '-'); + removeButton.setAttribute('class', 'zotero-clicky zotero-clicky-minus'); + removeButton.addEventListener('click', function () { + onDelete(id) + }); + } + + var row = document.createElement('row'); + row.appendChild(box); + if (editable) { + row.appendChild(removeButton); + } + + list.appendChild(row); + } + } + + this.addPDFTabContext = function(tabID, itemID) { + let contextualDeck = document.getElementById('zotero-item-pane-contextual-deck'); + + let container = document.createElement('vbox'); + container.id = tabID + '-context'; + + let bar = document.createElement('hbox'); + container.appendChild(bar); + let inner = document.createElement('deck'); + inner.style.backgroundColor = 'white'; + inner.setAttribute('flex', 1); + container.appendChild(inner); + + contextualDeck.appendChild(container); + + let item = Zotero.Items.get(itemID); + if (!item.parentID) { + inner.append("The PDF doesn't have a parent"); + return; + } + + let parentItem = Zotero.Items.get(item.parentID); + let returnButton = document.createElement('toolbarbutton'); + returnButton.className = 'zotero-tb-button'; + returnButton.id = 'zotero-tb-return'; + returnButton.style.listStyleImage = "url('chrome://zotero/skin/citation-delete.png')" + returnButton.addEventListener('click', () => { + inner.setAttribute('selectedIndex', 0); + }); + + bar.append(returnButton, parentItem.getField('title')); + bar.style.overflowX = 'hidden'; + bar.style.textOverflow = 'ellipsis'; + bar.style.fontWeight = 'bold'; + + let list = document.createElement('vbox'); + list.setAttribute('flex', 1); + list.className = 'zotero-box'; + + let note = document.createElement('zoteronoteeditor'); + note.setAttribute('flex', 1); + inner.appendChild(list); + inner.appendChild(note); + inner.setAttribute('selectedIndex', 0); + + note.placeholder = 'Drag annotations and write item-specific notes'; + + let head = document.createElement('hbox'); + head.setAttribute('align', 'center'); + let label = document.createElement('label'); + let button = document.createElement('button'); + button.setAttribute('label', 'Add'); + button.addEventListener('click', async () => { + inner.setAttribute('selectedIndex', 1); + let item = new Zotero.Item('note'); + item.libraryID = parentItem.libraryID; + item.parentKey = parentItem.key; + await item.saveTx(); + note.mode = 'edit'; + note.item = item; + note.parentItem = null; + _updateList(); + }); + head.append(label, button); + + let grid = document.createElement('grid'); + grid.setAttribute('flex', 1); + let columns = document.createElement('columns'); + let column1 = document.createElement('column'); + column1.setAttribute('flex', 1); + let column2 = document.createElement('column'); + columns.append(column1, column2); + grid.append(columns); + let rows = document.createElement('rows'); + rows.setAttribute('flex', 1); + grid.append(rows); + + list.append(head, grid); + + let parentNotes = parentItem.getNotes(); + if (parentNotes.length == 0) { + inner.setAttribute('selectedIndex', 1); + let item = new Zotero.Item('note'); + item.libraryID = parentItem.libraryID; + item.parentKey = parentItem.key; + note.mode = 'edit'; + note.item = item; + note.parentItem = null; + } + else if (parentNotes.length == 1) { + inner.setAttribute('selectedIndex', 1); + note.mode = 'edit'; + note.item = Zotero.Items.get(parentNotes[0]); + note.parentItem = null; + } + + let _updateList = () => { + while (rows.hasChildNodes()) { + rows.removeChild(rows.firstChild); + } + let parentNotes = Zotero.Items.get(parentItem.getNotes()); + this._appendNoteRows(parentNotes, rows, true, (id) => { + inner.setAttribute('selectedIndex', 1); + note.mode = 'edit'; + note.item = Zotero.Items.get(id); + note.parentItem = null; + }, (id) => { + ZoteroItemPane.removeNote(id); + }); + } + + _updateList(); + } + + this.removeTabContext = function(tabID) { + document.getElementById(tabID + '-context').remove(); + }; + + this.selectTabContext = function(tabID, type) { + let contextualDeck = document.getElementById('zotero-item-pane-contextual-deck'); + contextualDeck.selectedIndex = Array.from(contextualDeck.children).findIndex(x => x.id == tabID + '-context'); + + let toolbar = document.getElementById('zotero-pane-horizontal-space'); + let extendedToolbar = document.getElementById('zotero-item-pane-padding-top'); + let itemPane = document.getElementById('zotero-item-pane'); + if (type == 'library') { + toolbar.hidden = false; + extendedToolbar.hidden = true; + itemPane.hidden = false; + } + else { + toolbar.hidden = true; + extendedToolbar.hidden = false; + } + }; + function _updateNoteCount() { var c = _notesList.childNodes.length; diff --git a/chrome/content/zotero/itemPane.xul b/chrome/content/zotero/itemPane.xul index a2d61c11b6..e7a1e4f41f 100644 --- a/chrome/content/zotero/itemPane.xul +++ b/chrome/content/zotero/itemPane.xul @@ -35,115 +35,125 @@ - - - - - + + + + + + + + + @@ -576,12 +577,9 @@ oncommand="ZoteroPane.updateToolbarPosition(); ZoteroPane.updateTagsBoxSize()"> - - - - - - + + + diff --git a/pdf-reader b/pdf-reader index acd34e852d..3d949e7c83 160000 --- a/pdf-reader +++ b/pdf-reader @@ -1 +1 @@ -Subproject commit acd34e852d38768c8f31e59aa7238d4d934081eb +Subproject commit 3d949e7c83a19af8afdd1de0fdb3f95dde4f4dea diff --git a/pdf-worker b/pdf-worker index 9067fc6a92..886e714d33 160000 --- a/pdf-worker +++ b/pdf-worker @@ -1 +1 @@ -Subproject commit 9067fc6a9245019b0a4670f8a2b5d81f9f36ad0f +Subproject commit 886e714d3344534b66370010e855ea857f460627 diff --git a/zotero-note-editor b/zotero-note-editor index 3e8ec22246..156459aaf4 160000 --- a/zotero-note-editor +++ b/zotero-note-editor @@ -1 +1 @@ -Subproject commit 3e8ec222463b2eb05c4fecd4c43b8b629311e583 +Subproject commit 156459aaf4dbba9dc91b10a4e8ecb1142e56484b