Restore tabs state (#2148)
This commit is contained in:
parent
f9035c8fda
commit
85b142ccb2
7 changed files with 243 additions and 68 deletions
|
@ -58,7 +58,7 @@ var ZoteroContextPane = new function () {
|
||||||
this.update = _update;
|
this.update = _update;
|
||||||
this.getActiveEditor = _getActiveEditor;
|
this.getActiveEditor = _getActiveEditor;
|
||||||
|
|
||||||
this.onLoad = function () {
|
this.init = function () {
|
||||||
if (!Zotero) {
|
if (!Zotero) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -83,8 +83,33 @@ var ZoteroContextPane = new function () {
|
||||||
else {
|
else {
|
||||||
_tabToolbar.style.right = 0;
|
_tabToolbar.style.right = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vbox
|
||||||
|
var vbox = document.createElement('vbox');
|
||||||
|
vbox.setAttribute('flex', '1');
|
||||||
|
|
||||||
_init();
|
_contextPaneInner.append(vbox);
|
||||||
|
|
||||||
|
// Toolbar extension
|
||||||
|
var toolbarExtension = document.createElement('box');
|
||||||
|
toolbarExtension.style.height = '32px';
|
||||||
|
toolbarExtension.id = 'zotero-context-toolbar-extension';
|
||||||
|
|
||||||
|
_panesDeck = document.createElement('deck');
|
||||||
|
_panesDeck.setAttribute('flex', 1);
|
||||||
|
_panesDeck.setAttribute('selectedIndex', 0);
|
||||||
|
|
||||||
|
vbox.append(toolbarExtension, _panesDeck);
|
||||||
|
|
||||||
|
// Item pane deck
|
||||||
|
_itemPaneDeck = document.createElement('deck');
|
||||||
|
// Notes pane deck
|
||||||
|
_notesPaneDeck = document.createElement('deck');
|
||||||
|
_notesPaneDeck.style.backgroundColor = 'white';
|
||||||
|
_notesPaneDeck.setAttribute('flex', 1);
|
||||||
|
_notesPaneDeck.className = 'notes-pane-deck';
|
||||||
|
|
||||||
|
_panesDeck.append(_itemPaneDeck, _notesPaneDeck);
|
||||||
|
|
||||||
this._notifierID = Zotero.Notifier.registerObserver(this, ['item', 'tab'], 'contextPane');
|
this._notifierID = Zotero.Notifier.registerObserver(this, ['item', 'tab'], 'contextPane');
|
||||||
window.addEventListener('resize', _update);
|
window.addEventListener('resize', _update);
|
||||||
|
@ -94,7 +119,7 @@ var ZoteroContextPane = new function () {
|
||||||
Zotero.Reader.onChangeSidebarOpen = _updatePaneWidth;
|
Zotero.Reader.onChangeSidebarOpen = _updatePaneWidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.onUnload = function () {
|
this.destroy = function () {
|
||||||
_itemToggle.removeEventListener('click', _toggleItemButton);
|
_itemToggle.removeEventListener('click', _toggleItemButton);
|
||||||
_notesToggle.removeEventListener('click', _toggleNotesButton);
|
_notesToggle.removeEventListener('click', _toggleNotesButton);
|
||||||
window.removeEventListener('resize', _update);
|
window.removeEventListener('resize', _update);
|
||||||
|
@ -106,7 +131,7 @@ var ZoteroContextPane = new function () {
|
||||||
_notesContexts = [];
|
_notesContexts = [];
|
||||||
};
|
};
|
||||||
|
|
||||||
this.notify = Zotero.Promise.coroutine(function* (action, type, ids, extraData) {
|
this.notify = function (action, type, ids, extraData) {
|
||||||
if (type == 'item') {
|
if (type == 'item') {
|
||||||
// Update, remove or re-create item panes
|
// Update, remove or re-create item panes
|
||||||
for (let context of _itemContexts.slice()) {
|
for (let context of _itemContexts.slice()) {
|
||||||
|
@ -174,14 +199,14 @@ var ZoteroContextPane = new function () {
|
||||||
|| !document.activeElement.closest('.context-node iframe[anonid="editor-view"]'))) {
|
|| !document.activeElement.closest('.context-node iframe[anonid="editor-view"]'))) {
|
||||||
reader.focus();
|
reader.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var attachment = await Zotero.Items.getAsync(reader.itemID);
|
||||||
|
if (attachment) {
|
||||||
|
_selectNotesContext(attachment.libraryID);
|
||||||
|
var notesContext = _getNotesContext(attachment.libraryID);
|
||||||
|
notesContext.updateFromCache();
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
||||||
var attachment = Zotero.Items.get(reader.itemID);
|
|
||||||
if (attachment) {
|
|
||||||
_selectNotesContext(attachment.libraryID);
|
|
||||||
var notesContext = _getNotesContext(attachment.libraryID);
|
|
||||||
notesContext.updateFromCache();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_contextPaneSplitter.setAttribute('hidden', false);
|
_contextPaneSplitter.setAttribute('hidden', false);
|
||||||
|
@ -193,7 +218,7 @@ var ZoteroContextPane = new function () {
|
||||||
_update();
|
_update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
function _toggleItemButton() {
|
function _toggleItemButton() {
|
||||||
_togglePane(0);
|
_togglePane(0);
|
||||||
|
@ -346,35 +371,6 @@ var ZoteroContextPane = new function () {
|
||||||
splitter.setAttribute('state', hide ? 'collapsed' : 'open');
|
splitter.setAttribute('state', hide ? 'collapsed' : 'open');
|
||||||
_update();
|
_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
function _init() {
|
|
||||||
// vbox
|
|
||||||
var vbox = document.createElement('vbox');
|
|
||||||
vbox.setAttribute('flex', '1');
|
|
||||||
|
|
||||||
_contextPaneInner.append(vbox);
|
|
||||||
|
|
||||||
// Toolbar extension
|
|
||||||
var toolbarExtension = document.createElement('box');
|
|
||||||
toolbarExtension.style.height = '32px';
|
|
||||||
toolbarExtension.id = 'zotero-context-toolbar-extension';
|
|
||||||
|
|
||||||
_panesDeck = document.createElement('deck');
|
|
||||||
_panesDeck.setAttribute('flex', 1);
|
|
||||||
_panesDeck.setAttribute('selectedIndex', 0);
|
|
||||||
|
|
||||||
vbox.append(toolbarExtension, _panesDeck);
|
|
||||||
|
|
||||||
// Item pane deck
|
|
||||||
_itemPaneDeck = document.createElement('deck');
|
|
||||||
// Notes pane deck
|
|
||||||
_notesPaneDeck = document.createElement('deck');
|
|
||||||
_notesPaneDeck.style.backgroundColor = 'white';
|
|
||||||
_notesPaneDeck.setAttribute('flex', 1);
|
|
||||||
_notesPaneDeck.className = 'notes-pane-deck';
|
|
||||||
|
|
||||||
_panesDeck.append(_itemPaneDeck, _notesPaneDeck);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _getCurrentAttachment() {
|
function _getCurrentAttachment() {
|
||||||
var reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID);
|
var reader = Zotero.Reader.getByTabID(Zotero_Tabs.selectedID);
|
||||||
|
@ -737,7 +733,16 @@ var ZoteroContextPane = new function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _addItemContext(tabID, itemID) {
|
async function _addItemContext(tabID, itemID) {
|
||||||
|
var container = document.createElement('vbox');
|
||||||
|
container.id = tabID + '-context';
|
||||||
|
container.className = 'zotero-item-pane-content';
|
||||||
|
_itemPaneDeck.appendChild(container);
|
||||||
|
|
||||||
|
var { libraryID } = Zotero.Items.getLibraryAndKeyFromID(itemID);
|
||||||
|
var library = Zotero.Libraries.get(libraryID);
|
||||||
|
await library.waitForDataLoad('item');
|
||||||
|
|
||||||
var item = Zotero.Items.get(itemID);
|
var item = Zotero.Items.get(itemID);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return;
|
return;
|
||||||
|
@ -745,11 +750,6 @@ var ZoteroContextPane = new function () {
|
||||||
var libraryID = item.libraryID;
|
var libraryID = item.libraryID;
|
||||||
var readOnly = _isLibraryReadOnly(libraryID);
|
var readOnly = _isLibraryReadOnly(libraryID);
|
||||||
var parentID = item.parentID;
|
var parentID = item.parentID;
|
||||||
|
|
||||||
var container = document.createElement('vbox');
|
|
||||||
container.id = tabID + '-context';
|
|
||||||
container.className = 'zotero-item-pane-content';
|
|
||||||
_itemPaneDeck.appendChild(container);
|
|
||||||
|
|
||||||
var context = {
|
var context = {
|
||||||
tabID,
|
tabID,
|
||||||
|
@ -786,6 +786,3 @@ var ZoteroContextPane = new function () {
|
||||||
itemBox.item = parentItem;
|
itemBox.item = parentItem;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
addEventListener('load', function (e) { ZoteroContextPane.onLoad(e); }, false);
|
|
||||||
addEventListener('unload', function (e) { ZoteroContextPane.onUnload(e); }, false);
|
|
||||||
|
|
|
@ -85,17 +85,53 @@ var Zotero_Tabs = new function () {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.getState = function () {
|
||||||
|
return this._tabs.map((tab) => {
|
||||||
|
var o = {
|
||||||
|
type: tab.type,
|
||||||
|
title: tab.title,
|
||||||
|
};
|
||||||
|
if (tab.data) {
|
||||||
|
o.data = tab.data;
|
||||||
|
}
|
||||||
|
if (tab.id == this._selectedID) {
|
||||||
|
o.selected = true;
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.restoreState = function(tabs) {
|
||||||
|
for (let tab of tabs) {
|
||||||
|
if (tab.type === 'library') {
|
||||||
|
this.rename('zotero-pane', tab.title);
|
||||||
|
}
|
||||||
|
else if (tab.type === 'reader') {
|
||||||
|
if (Zotero.Items.exists(tab.data.itemID)) {
|
||||||
|
Zotero.Reader.open(tab.data.itemID,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
title: tab.title,
|
||||||
|
openInBackground: !tab.selected
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new tab
|
* Add a new tab
|
||||||
*
|
*
|
||||||
* @param {String} type
|
* @param {String} type
|
||||||
* @param {String} title
|
* @param {String} title
|
||||||
|
* @param {String} data - Extra data about the tab to pass to notifier and session
|
||||||
* @param {Integer} index
|
* @param {Integer} index
|
||||||
* @param {Boolean} select
|
* @param {Boolean} select
|
||||||
* @param {Function} onClose
|
* @param {Function} onClose
|
||||||
* @return {{ id: string, container: XULElement}} id - tab id, container - a new tab container created in the deck
|
* @return {{ id: string, container: XULElement}} id - tab id, container - a new tab container created in the deck
|
||||||
*/
|
*/
|
||||||
this.add = function ({ type, title, index, select, onClose, notifierData }) {
|
this.add = function ({ type, data, title, index, select, onClose }) {
|
||||||
if (typeof type != 'string') {
|
if (typeof type != 'string') {
|
||||||
throw new Error(`'type' should be a string (was ${typeof type})`);
|
throw new Error(`'type' should be a string (was ${typeof type})`);
|
||||||
}
|
}
|
||||||
|
@ -112,11 +148,11 @@ var Zotero_Tabs = new function () {
|
||||||
var container = document.createElement('vbox');
|
var container = document.createElement('vbox');
|
||||||
container.id = id;
|
container.id = id;
|
||||||
this.deck.appendChild(container);
|
this.deck.appendChild(container);
|
||||||
var tab = { id, type, title, onClose };
|
var tab = { id, type, title, data, onClose };
|
||||||
index = index || this._tabs.length;
|
index = index || this._tabs.length;
|
||||||
this._tabs.splice(index, 0, tab);
|
this._tabs.splice(index, 0, tab);
|
||||||
this._update();
|
this._update();
|
||||||
Zotero.Notifier.trigger('add', 'tab', [id], { [id]: notifierData }, true);
|
Zotero.Notifier.trigger('add', 'tab', [id], { [id]: data }, true);
|
||||||
if (select) {
|
if (select) {
|
||||||
this.select(id);
|
this.select(id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ class ReaderInstance {
|
||||||
this._window = null;
|
this._window = null;
|
||||||
this._iframeWindow = null;
|
this._iframeWindow = null;
|
||||||
this._itemID = null;
|
this._itemID = null;
|
||||||
|
this._title = '';
|
||||||
this._isReaderInitialized = false;
|
this._isReaderInitialized = false;
|
||||||
this._showItemPaneToggle = false;
|
this._showItemPaneToggle = false;
|
||||||
this._initPromise = new Promise((resolve, reject) => {
|
this._initPromise = new Promise((resolve, reject) => {
|
||||||
|
@ -50,7 +51,11 @@ class ReaderInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
async open({ itemID, state, location }) {
|
async open({ itemID, state, location }) {
|
||||||
let item = await Zotero.Items.getAsync(itemID);
|
let { libraryID } = Zotero.Items.getLibraryAndKeyFromID(itemID);
|
||||||
|
let library = Zotero.Libraries.get(libraryID);
|
||||||
|
await library.waitForDataLoad('item');
|
||||||
|
|
||||||
|
let item = Zotero.Items.get(itemID);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -101,6 +106,7 @@ class ReaderInstance {
|
||||||
title = parentItem.getDisplayTitle();
|
title = parentItem.getDisplayTitle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this._title = title;
|
||||||
this._setTitleValue(title);
|
this._setTitleValue(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,7 +650,7 @@ class ReaderInstance {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReaderTab extends ReaderInstance {
|
class ReaderTab extends ReaderInstance {
|
||||||
constructor({ itemID, sidebarWidth, sidebarOpen, bottomPlaceholderHeight }) {
|
constructor({ itemID, title, sidebarWidth, sidebarOpen, bottomPlaceholderHeight, background }) {
|
||||||
super();
|
super();
|
||||||
this._itemID = itemID;
|
this._itemID = itemID;
|
||||||
this._sidebarWidth = sidebarWidth;
|
this._sidebarWidth = sidebarWidth;
|
||||||
|
@ -654,11 +660,11 @@ class ReaderTab extends ReaderInstance {
|
||||||
this._window = Services.wm.getMostRecentWindow('navigator:browser');
|
this._window = Services.wm.getMostRecentWindow('navigator:browser');
|
||||||
let { id, container } = this._window.Zotero_Tabs.add({
|
let { id, container } = this._window.Zotero_Tabs.add({
|
||||||
type: 'reader',
|
type: 'reader',
|
||||||
title: '',
|
title: title || '',
|
||||||
select: true,
|
data: {
|
||||||
notifierData: {
|
|
||||||
itemID
|
itemID
|
||||||
}
|
},
|
||||||
|
select: !background
|
||||||
});
|
});
|
||||||
this.tabID = id;
|
this.tabID = id;
|
||||||
this._tabContainer = container;
|
this._tabContainer = container;
|
||||||
|
@ -832,6 +838,13 @@ class Reader {
|
||||||
return this._sidebarWidth;
|
return this._sidebarWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
await Zotero.uiReadyPromise;
|
||||||
|
Zotero.Session.state.windows
|
||||||
|
.filter(x => x.type == 'reader' && Zotero.Items.exists(x.itemID))
|
||||||
|
.forEach(x => this.open(x.itemID, null, { title: x.title, openInWindow: true }));
|
||||||
|
}
|
||||||
|
|
||||||
_loadSidebarOpenState() {
|
_loadSidebarOpenState() {
|
||||||
let win = Zotero.getMainWindow();
|
let win = Zotero.getMainWindow();
|
||||||
if (win) {
|
if (win) {
|
||||||
|
@ -888,6 +901,10 @@ class Reader {
|
||||||
this.triggerAnnotationsImportCheck(reader._itemID);
|
this.triggerAnnotationsImportCheck(reader._itemID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event === 'add' || event === 'close') {
|
||||||
|
Zotero.Session.debounceSave();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Listen for parent item, PDF attachment and its annotations updates
|
// Listen for parent item, PDF attachment and its annotations updates
|
||||||
else if (type === 'item') {
|
else if (type === 'item') {
|
||||||
|
@ -932,19 +949,25 @@ class Reader {
|
||||||
getByTabID(tabID) {
|
getByTabID(tabID) {
|
||||||
return this._readers.find(r => (r instanceof ReaderTab) && r.tabID === tabID);
|
return this._readers.find(r => (r instanceof ReaderTab) && r.tabID === tabID);
|
||||||
}
|
}
|
||||||
|
|
||||||
async openURI(itemURI, location, openWindow) {
|
getWindowStates() {
|
||||||
let item = await Zotero.URI.getURIItem(itemURI);
|
return this._readers
|
||||||
if (!item) return;
|
.filter(r => r instanceof ReaderWindow)
|
||||||
await this.open(item.id, location, openWindow);
|
.map(r => ({ type: 'reader', itemID: r._itemID, title: r._title }));
|
||||||
}
|
}
|
||||||
|
|
||||||
async open(itemID, location, openWindow) {
|
async openURI(itemURI, location, options) {
|
||||||
|
let item = await Zotero.URI.getURIItem(itemURI);
|
||||||
|
if (!item) return;
|
||||||
|
await this.open(item.id, location, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
async open(itemID, location, { title, openInBackground, openInWindow } = {}) {
|
||||||
this._loadSidebarOpenState();
|
this._loadSidebarOpenState();
|
||||||
this.triggerAnnotationsImportCheck(itemID);
|
this.triggerAnnotationsImportCheck(itemID);
|
||||||
let reader;
|
let reader;
|
||||||
|
|
||||||
if (openWindow) {
|
if (openInWindow) {
|
||||||
reader = this._readers.find(r => r._itemID === itemID && (r instanceof ReaderWindow));
|
reader = this._readers.find(r => r._itemID === itemID && (r instanceof ReaderWindow));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -960,7 +983,7 @@ class Reader {
|
||||||
reader.navigate(location);
|
reader.navigate(location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (openWindow) {
|
else if (openInWindow) {
|
||||||
reader = new ReaderWindow({
|
reader = new ReaderWindow({
|
||||||
sidebarWidth: this._sidebarWidth,
|
sidebarWidth: this._sidebarWidth,
|
||||||
sidebarOpen: this._sidebarOpen,
|
sidebarOpen: this._sidebarOpen,
|
||||||
|
@ -970,13 +993,17 @@ class Reader {
|
||||||
if (!(await reader.open({ itemID, location }))) {
|
if (!(await reader.open({ itemID, location }))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Zotero.Session.debounceSave();
|
||||||
reader._window.addEventListener('unload', () => {
|
reader._window.addEventListener('unload', () => {
|
||||||
this._readers.splice(this._readers.indexOf(reader), 1);
|
this._readers.splice(this._readers.indexOf(reader), 1);
|
||||||
|
Zotero.Session.debounceSave();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
reader = new ReaderTab({
|
reader = new ReaderTab({
|
||||||
itemID,
|
itemID,
|
||||||
|
title,
|
||||||
|
background: openInBackground,
|
||||||
sidebarWidth: this._sidebarWidth,
|
sidebarWidth: this._sidebarWidth,
|
||||||
sidebarOpen: this._sidebarOpen,
|
sidebarOpen: this._sidebarOpen,
|
||||||
bottomPlaceholderHeight: this._bottomPlaceholderHeight
|
bottomPlaceholderHeight: this._bottomPlaceholderHeight
|
||||||
|
|
80
chrome/content/zotero/xpcom/session.js
Normal file
80
chrome/content/zotero/xpcom/session.js
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright © 2021 Corporation for Digital Scholarship
|
||||||
|
Vienna, Virginia, USA
|
||||||
|
http://digitalscholar.org/
|
||||||
|
|
||||||
|
This file is part of Zotero.
|
||||||
|
|
||||||
|
Zotero is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Zotero is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
Zotero.Session = new function () {
|
||||||
|
const SESSION_FILE_NAME = 'session.json';
|
||||||
|
const DEBOUNCED_SAVING_DELAY = 5 * 60 * 1000; // 5 min
|
||||||
|
|
||||||
|
let _state = {
|
||||||
|
windows: []
|
||||||
|
};
|
||||||
|
|
||||||
|
Zotero.defineProperty(this, 'state', {
|
||||||
|
get: () => {
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.init = async function () {
|
||||||
|
try {
|
||||||
|
let sessionFile = OS.Path.join(Zotero.Profile.dir, SESSION_FILE_NAME);
|
||||||
|
let state = await Zotero.File.getContentsAsync(sessionFile);
|
||||||
|
_state = JSON.parse(state);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
Zotero.logError(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setLastClosedZoteroPaneState = function (state) {
|
||||||
|
_state.windows = [state];
|
||||||
|
};
|
||||||
|
|
||||||
|
this.debounceSave = Zotero.Utilities.debounce(() => {
|
||||||
|
this.save();
|
||||||
|
}, DEBOUNCED_SAVING_DELAY);
|
||||||
|
|
||||||
|
this.save = async function () {
|
||||||
|
try {
|
||||||
|
// Saving is triggered in `zotero.js` when a quit event is received,
|
||||||
|
// though if it was triggered by closing a window, ZoteroPane might
|
||||||
|
// be already destroyed at the time
|
||||||
|
let panes = Zotero.getZoteroPanes().map(x => x.getState());
|
||||||
|
let readers = Zotero.Reader.getWindowStates();
|
||||||
|
if (panes.length) {
|
||||||
|
_state.windows = [...readers, ...panes];
|
||||||
|
}
|
||||||
|
else if (readers.length) {
|
||||||
|
_state.windows = _state.windows.filter(x => x.type != 'reader');
|
||||||
|
_state.windows = [..._state.windows, ...readers];
|
||||||
|
}
|
||||||
|
let sessionFile = OS.Path.join(Zotero.Profile.dir, SESSION_FILE_NAME);
|
||||||
|
await Zotero.File.putContentsAsync(sessionFile, JSON.stringify(_state));
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
Zotero.logError(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
|
@ -380,6 +380,12 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js");
|
||||||
// Make sure data directory isn't in Dropbox, etc.
|
// Make sure data directory isn't in Dropbox, etc.
|
||||||
yield Zotero.DataDirectory.checkForUnsafeLocation(dataDir);
|
yield Zotero.DataDirectory.checkForUnsafeLocation(dataDir);
|
||||||
|
|
||||||
|
Services.obs.addObserver({
|
||||||
|
observe: function () {
|
||||||
|
Zotero.Session.save();
|
||||||
|
}
|
||||||
|
}, "quit-application-granted", false);
|
||||||
|
|
||||||
// Register shutdown handler to call Zotero.shutdown()
|
// Register shutdown handler to call Zotero.shutdown()
|
||||||
var _shutdownObserver = {observe:function() { Zotero.shutdown().done() }};
|
var _shutdownObserver = {observe:function() { Zotero.shutdown().done() }};
|
||||||
Services.obs.addObserver(_shutdownObserver, "quit-application", false);
|
Services.obs.addObserver(_shutdownObserver, "quit-application", false);
|
||||||
|
@ -690,6 +696,8 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js");
|
||||||
yield Zotero.CharacterSets.init();
|
yield Zotero.CharacterSets.init();
|
||||||
yield Zotero.RelationPredicates.init();
|
yield Zotero.RelationPredicates.init();
|
||||||
|
|
||||||
|
yield Zotero.Session.init();
|
||||||
|
|
||||||
Zotero.locked = false;
|
Zotero.locked = false;
|
||||||
|
|
||||||
// Initialize various services
|
// Initialize various services
|
||||||
|
@ -727,6 +735,7 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js");
|
||||||
yield Zotero.Retractions.init();
|
yield Zotero.Retractions.init();
|
||||||
yield Zotero.NoteBackups.init();
|
yield Zotero.NoteBackups.init();
|
||||||
yield Zotero.Dictionaries.init();
|
yield Zotero.Dictionaries.init();
|
||||||
|
Zotero.Reader.init();
|
||||||
|
|
||||||
// Migrate fields from Extra that can be moved to item fields after a schema update
|
// Migrate fields from Extra that can be moved to item fields after a schema update
|
||||||
yield Zotero.Schema.migrateExtraFields();
|
yield Zotero.Schema.migrateExtraFields();
|
||||||
|
|
|
@ -153,6 +153,7 @@ var ZoteroPane = new function()
|
||||||
Zotero.hiDPISuffix = Zotero.hiDPI ? "@2x" : "";
|
Zotero.hiDPISuffix = Zotero.hiDPI ? "@2x" : "";
|
||||||
|
|
||||||
Zotero_Tabs.init();
|
Zotero_Tabs.init();
|
||||||
|
ZoteroContextPane.init();
|
||||||
await ZoteroPane.initCollectionsTree();
|
await ZoteroPane.initCollectionsTree();
|
||||||
await ZoteroPane.initItemsTree();
|
await ZoteroPane.initItemsTree();
|
||||||
|
|
||||||
|
@ -248,6 +249,17 @@ var ZoteroPane = new function()
|
||||||
var importer = new Zotero_Import_Mendeley();
|
var importer = new Zotero_Import_Mendeley();
|
||||||
importer.deleteNonPrimaryFiles();
|
importer.deleteNonPrimaryFiles();
|
||||||
}, 10000)
|
}, 10000)
|
||||||
|
|
||||||
|
// Restore pane state
|
||||||
|
try {
|
||||||
|
let state = Zotero.Session.state.windows.find(x => x.type == 'pane');
|
||||||
|
if (state) {
|
||||||
|
Zotero_Tabs.restoreState(state.tabs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
Zotero.logError(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -355,6 +367,12 @@ var ZoteroPane = new function()
|
||||||
|
|
||||||
observerService.removeObserver(_reloadObserver, "zotero-reloaded");
|
observerService.removeObserver(_reloadObserver, "zotero-reloaded");
|
||||||
|
|
||||||
|
ZoteroContextPane.destroy();
|
||||||
|
|
||||||
|
if (!Zotero.getZoteroPanes().length) {
|
||||||
|
Zotero.Session.setLastClosedZoteroPaneState(this.getState());
|
||||||
|
}
|
||||||
|
|
||||||
Zotero_Tabs.closeAll();
|
Zotero_Tabs.closeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3801,7 +3819,7 @@ var ZoteroPane = new function()
|
||||||
await Zotero.Reader.open(
|
await Zotero.Reader.open(
|
||||||
itemID,
|
itemID,
|
||||||
extraData && extraData.location,
|
extraData && extraData.location,
|
||||||
originalEvent && originalEvent.shiftKey
|
{ openInWindow: originalEvent && originalEvent.shiftKey }
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -4855,6 +4873,13 @@ var ZoteroPane = new function()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.getState = function () {
|
||||||
|
return {
|
||||||
|
type: 'pane',
|
||||||
|
tabs: Zotero_Tabs.getState()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unserializes zotero-persist elements from preferences
|
* Unserializes zotero-persist elements from preferences
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -120,6 +120,7 @@ const xpcomFilesLocal = [
|
||||||
'router',
|
'router',
|
||||||
'schema',
|
'schema',
|
||||||
'server',
|
'server',
|
||||||
|
'session',
|
||||||
'streamer',
|
'streamer',
|
||||||
'style',
|
'style',
|
||||||
'sync',
|
'sync',
|
||||||
|
|
Loading…
Reference in a new issue