Consolidate Integration.Fields into Integration.Session

This commit is contained in:
Adomas Venčkauskas 2020-07-30 15:42:54 +03:00 committed by Dan Stillman
parent 3701b84116
commit 2b3669afd8
2 changed files with 156 additions and 164 deletions

View file

@ -211,7 +211,7 @@ Zotero.Integration = new function() {
await document.setDocumentData(session.data.serialize());
// And any citations marked for processing (like retraction warning ignore flag changes)
if (Object.keys(session.processIndices).length) {
session.fields.updateDocument(FORCE_CITATIONS_FALSE, false, false);
session.updateDocument(FORCE_CITATIONS_FALSE, false, false);
}
}
}
@ -422,8 +422,12 @@ Zotero.Integration = new function() {
session.agent = agent;
session._doc = doc;
session.progressBar = progressBar;
// TODO: this is a pretty awful circular dependence
session.fields = new Zotero.Integration.Fields(session, doc);
session._fields = null;
session.ignoreEmptyBibliography = true;
session.progressCallback = null;
session._removeCodeFields = {};
session._deleteFields = {};
session._bibliographyFields = [];
if (dataString == EXPORTED_DOCUMENT_MARKER) {
Zotero.Integration.currentSession = session;
@ -548,13 +552,13 @@ Zotero.Integration.Interface = function(app, doc, session) {
Zotero.Integration.Interface.prototype.addCitation = Zotero.Promise.coroutine(function* () {
yield this._session.init(false, false);
let [idx, field, citation] = yield this._session.fields.addEditCitation(null);
let [idx, field, citation] = yield this._session.cite(null);
yield this._session.addCitation(idx, yield field.getNoteIndex(), citation);
if (this._session.data.prefs.delayCitationUpdates) {
return this._session.writeDelayedCitation(field, citation);
} else {
return this._session.fields.updateDocument(FORCE_CITATIONS_FALSE, false, false);
return this._session.updateDocument(FORCE_CITATIONS_FALSE, false, false);
}
});
@ -580,12 +584,12 @@ Zotero.Integration.Interface.prototype.addEditCitation = async function (docFiel
await this._session.init(false, false);
docField = docField || await this._doc.cursorInField(this._session.data.prefs['fieldType']);
let [idx, field, citation] = await this._session.fields.addEditCitation(docField);
let [idx, field, citation] = await this._session.cite(docField);
await this._session.addCitation(idx, await field.getNoteIndex(), citation);
if (this._session.data.prefs.delayCitationUpdates) {
return this._session.writeDelayedCitation(field, citation);
} else {
return this._session.fields.updateDocument(FORCE_CITATIONS_FALSE, false, false);
return this._session.updateDocument(FORCE_CITATIONS_FALSE, false, false);
}
};
@ -602,7 +606,7 @@ Zotero.Integration.Interface.prototype.addBibliography = Zotero.Promise.coroutin
"integration.error.title");
}
let field = new Zotero.Integration.BibliographyField(yield this._session.fields.addField());
let field = new Zotero.Integration.BibliographyField(yield this._session.addField());
var citationsMode = FORCE_CITATIONS_FALSE;
yield field.clearCode();
if(this._session.data.prefs.delayCitationUpdates) {
@ -610,8 +614,8 @@ Zotero.Integration.Interface.prototype.addBibliography = Zotero.Promise.coroutin
this._session.reload = true;
citationsMode = FORCE_CITATIONS_REGENERATE;
}
yield this._session.fields.updateSession(citationsMode);
yield this._session.fields.updateDocument(citationsMode, true, false);
yield this._session.updateFromDocument(citationsMode);
yield this._session.updateDocument(citationsMode, true, false);
})
/**
@ -621,7 +625,7 @@ Zotero.Integration.Interface.prototype.addBibliography = Zotero.Promise.coroutin
Zotero.Integration.Interface.prototype.editBibliography = Zotero.Promise.coroutine(function*() {
// Make sure we have a bibliography
yield this._session.init(true, false);
var fields = yield this._session.fields.get();
var fields = yield this._session.getFields();
var bibliographyField;
for (let i = fields.length-1; i >= 0; i--) {
@ -643,9 +647,9 @@ Zotero.Integration.Interface.prototype.editBibliography = Zotero.Promise.corouti
this._session.reload = true;
citationsMode = FORCE_CITATIONS_REGENERATE;
}
yield this._session.fields.updateSession(citationsMode);
yield this._session.updateFromDocument(citationsMode);
yield this._session.editBibliography(bibliography);
yield this._session.fields.updateDocument(citationsMode, true, false);
yield this._session.updateDocument(citationsMode, true, false);
});
@ -658,7 +662,7 @@ Zotero.Integration.Interface.prototype.addEditBibliography = Zotero.Promise.coro
"integration.error.title");
}
var fields = yield this._session.fields.get();
var fields = yield this._session.getFields();
var bibliographyField;
for (let i = fields.length-1; i >= 0; i--) {
@ -671,7 +675,7 @@ Zotero.Integration.Interface.prototype.addEditBibliography = Zotero.Promise.coro
var newBibliography = !bibliographyField;
if (!bibliographyField) {
bibliographyField = new Zotero.Integration.BibliographyField(yield this._session.fields.addField());
bibliographyField = new Zotero.Integration.BibliographyField(yield this._session.addField());
yield bibliographyField.clearCode();
}
@ -682,9 +686,9 @@ Zotero.Integration.Interface.prototype.addEditBibliography = Zotero.Promise.coro
this._session.reload = true;
citationsMode = FORCE_CITATIONS_REGENERATE;
}
yield this._session.fields.updateSession(citationsMode);
yield this._session.updateFromDocument(citationsMode);
if (!newBibliography) yield this._session.editBibliography(bibliography);
yield this._session.fields.updateDocument(citationsMode, true, false);
yield this._session.updateDocument(citationsMode, true, false);
});
/**
@ -695,8 +699,8 @@ Zotero.Integration.Interface.prototype.refresh = async function() {
await this._session.init(true, false)
this._session.reload = this._session.reload || this._session.data.prefs.delayCitationUpdates;
await this._session.fields.updateSession(FORCE_CITATIONS_REGENERATE)
await this._session.fields.updateDocument(FORCE_CITATIONS_REGENERATE, true, false);
await this._session.updateFromDocument(FORCE_CITATIONS_REGENERATE);
await this._session.updateDocument(FORCE_CITATIONS_REGENERATE, true, false);
}
/**
@ -704,10 +708,9 @@ Zotero.Integration.Interface.prototype.refresh = async function() {
* @return {Promise}
*/
Zotero.Integration.Interface.prototype.removeCodes = Zotero.Promise.coroutine(function* () {
var me = this;
yield this._session.init(true, false)
let fields = yield this._session.fields.get()
var result = yield me._doc.displayAlert(Zotero.getString("integration.removeCodesWarning"),
let fields = yield this._session.getFields()
var result = yield this._doc.displayAlert(Zotero.getString("integration.removeCodesWarning"),
DIALOG_ICON_WARNING, DIALOG_BUTTONS_OK_CANCEL);
if (result) {
for(var i=fields.length-1; i>=0; i--) {
@ -730,7 +733,7 @@ Zotero.Integration.Interface.prototype.setDocPrefs = Zotero.Promise.coroutine(fu
} else {
// Can get fields while dialog is open
oldData = yield Zotero.Promise.all([
this._session.fields.get(),
this._session.getFields(),
this._session.setDocPrefs(true)
]).spread(function (fields, setDocPrefs) {
// Only return value from setDocPrefs
@ -743,7 +746,7 @@ Zotero.Integration.Interface.prototype.setDocPrefs = Zotero.Promise.coroutine(fu
if (!oldData) return false;
// Perform noteType or fieldType conversion
let fields = yield this._session.fields.get();
let fields = yield this._session.getFields();
var convertBibliographies = oldData.prefs.fieldType != this._session.data.prefs.fieldType;
var convertItems = convertBibliographies
@ -773,14 +776,14 @@ Zotero.Integration.Interface.prototype.setDocPrefs = Zotero.Promise.coroutine(fu
fieldNoteTypes.length);
}
// Refresh contents
this._session.fields = new Zotero.Integration.Fields(this._session, this._doc);
this._session.fields.ignoreEmptyBibliography = false;
// Refresh field info
this._session._fields = null;
this._session.ignoreEmptyBibliography = true;
if (this._session.data.prefs.delayCitationUpdates && !fieldsToConvert.length) return;
yield this._session.fields.updateSession(FORCE_CITATIONS_RESET_TEXT);
return this._session.fields.updateDocument(FORCE_CITATIONS_RESET_TEXT, true, true);
yield this._session.updateFromDocument(FORCE_CITATIONS_RESET_TEXT);
return this._session.updateDocument(FORCE_CITATIONS_RESET_TEXT, true, true);
});
/**
@ -808,37 +811,48 @@ Zotero.Integration.JSEnumerator.prototype.getNext = function() {
}
/**
* Methods for retrieving fields from a document
* @constructor
* Keeps track of all session-specific variables
*/
Zotero.Integration.Fields = function(session, doc) {
Zotero.Integration.Session = function(doc, app) {
this.embeddedItems = {};
this.embeddedZoteroItems = {};
this.embeddedItemsByURI = {};
this.citationsByIndex = {};
this.resetRequest(doc);
this.primaryFieldType = app.primaryFieldType;
this.secondaryFieldType = app.secondaryFieldType;
this.outputFormat = app.outputFormat || 'rtf';
this._sessionUpToDate = false;
this._app = app;
this._fields = null;
this.ignoreEmptyBibliography = true;
// Callback called while retrieving fields with the percentage complete.
this.progressCallback = null;
this._session = session;
this._doc = doc;
this._removeCodeFields = {};
this._deleteFields = {};
this._bibliographyFields = [];
this.sessionID = Zotero.randomString();
Zotero.Integration.sessions[this.sessionID] = this;
}
/**
* Checks that it is appropriate to add fields to the current document at the current
* position, then adds one.
*/
Zotero.Integration.Fields.prototype.addField = async function(note) {
Zotero.Integration.Session.prototype.addField = async function(note) {
// Get citation types if necessary
if (!await this._doc.canInsertField(this._session.data.prefs['fieldType'])) {
if (!await this._doc.canInsertField(this.data.prefs['fieldType'])) {
return Zotero.Promise.reject(new Zotero.Exception.Alert("integration.error.cannotInsertHere",
[], "integration.error.title"));
}
var field = await this._doc.cursorInField(this._session.data.prefs['fieldType']);
var field = await this._doc.cursorInField(this.data.prefs['fieldType']);
if (field) {
if (!await this._session.displayAlert(Zotero.getString("integration.replace"),
if (!await this.displayAlert(Zotero.getString("integration.replace"),
DIALOG_ICON_STOP,
DIALOG_BUTTONS_OK_CANCEL)) {
return Zotero.Promise.reject(new Zotero.Exception.UserCancelled("inserting citation"));
@ -846,13 +860,13 @@ Zotero.Integration.Fields.prototype.addField = async function(note) {
}
if (!field) {
field = await this._doc.insertField(this._session.data.prefs['fieldType'],
(note ? this._session.data.prefs["noteType"] : 0));
field = await this._doc.insertField(this.data.prefs['fieldType'],
(note ? this.data.prefs["noteType"] : 0));
// Older doc plugins do not initialize the field code to anything meaningful
// so we ensure it here manually
field.setCode('TEMP');
}
// If fields already retrieved, further this.get() calls will returned the cached version
// If fields already retrieved, further this.getFields() calls will returned the cached version
// So we append this field to that list
if (this._fields) {
this._fields.push(field);
@ -865,7 +879,7 @@ Zotero.Integration.Fields.prototype.addField = async function(note) {
* Gets all fields for a document
* @return {Promise} Promise resolved with field list.
*/
Zotero.Integration.Fields.prototype.get = new function() {
Zotero.Integration.Session.prototype.getFields = new function() {
var deferred;
return async function(force=false) {
// If we already have fields, just return them
@ -882,12 +896,12 @@ Zotero.Integration.Fields.prototype.get = new function() {
// Otherwise, start getting fields
var timer = new Zotero.Integration.Timer();
timer.start();
this._session.progressBar.start();
this.progressBar.start();
try {
var fields = this._fields = Array.from(await this._doc.getFields(this._session.data.prefs['fieldType']));
var fields = this._fields = Array.from(await this._doc.getFields(this.data.prefs['fieldType']));
var retrieveTime = timer.stop();
this._session.progressBar.finishSegment();
this.progressBar.finishSegment();
Zotero.debug("Integration: Retrieved " + fields.length + " fields in " +
retrieveTime + "; " + fields.length/retrieveTime + " fields/second");
deferred.resolve(fields);
@ -901,11 +915,11 @@ Zotero.Integration.Fields.prototype.get = new function() {
}
/**
* Updates Zotero.Integration.Session attached to Zotero.Integration.Fields in line with document
* Updates Zotero.Integration.Session citations from the session document
*/
Zotero.Integration.Fields.prototype.updateSession = Zotero.Promise.coroutine(function* (forceCitations) {
yield this.get();
this._session.resetRequest(this._doc);
Zotero.Integration.Session.prototype.updateFromDocument = Zotero.Promise.coroutine(function* (forceCitations) {
yield this.getFields();
this.resetRequest(this._doc);
this._removeCodeFields = {};
this._deleteFields = {};
@ -913,50 +927,50 @@ Zotero.Integration.Fields.prototype.updateSession = Zotero.Promise.coroutine(fun
var timer = new Zotero.Integration.Timer();
timer.start();
this._session.progressBar.start();
this.progressBar.start();
if (forceCitations) {
this._session.regenAll = true;
this.regenAll = true;
}
yield this._processFields();
try {
yield this._session.handleRetractedItems();
yield this.handleRetractedItems();
}
catch (e) {
Zotero.debug('Retracted item handling failed', 2);
Zotero.logError(e);
}
this._session.regenAll = false;
this.regenAll = false;
var updateTime = timer.stop();
this._session.progressBar.finishSegment();
this.progressBar.finishSegment();
Zotero.debug("Integration: Updated session data for " + this._fields.length + " fields in "
+ updateTime + "; " + this._fields.length/updateTime + " fields/second");
if (this._session.reload) {
this._session.restoreProcessorState();
delete this._session.reload;
if (this.reload) {
this.restoreProcessorState();
delete this.reload;
}
this._session._sessionUpToDate = true;
this._sessionUpToDate = true;
});
/**
* Keep processing fields until all have been processed
*/
Zotero.Integration.Fields.prototype._processFields = Zotero.Promise.coroutine(function* () {
Zotero.Integration.Session.prototype._processFields = async function () {
if (!this._fields) {
throw new Error("_processFields called without fetching fields first");
}
for (var i = 0; i < this._fields.length; i++) {
let field = yield Zotero.Integration.Field.loadExisting(this._fields[i]);
let field = await Zotero.Integration.Field.loadExisting(this._fields[i]);
if (field.type === INTEGRATION_TYPE_ITEM) {
var noteIndex = yield field.getNoteIndex(),
data = yield field.unserialize(),
var noteIndex = await field.getNoteIndex(),
data = await field.unserialize(),
citation = new Zotero.Integration.Citation(field, data, noteIndex);
yield this._session.addCitation(i, noteIndex, citation);
await this.addCitation(i, noteIndex, citation);
} else if (field.type === INTEGRATION_TYPE_BIBLIOGRAPHY) {
if (this.ignoreEmptyBibliography && (yield field.getText()).trim() === "") {
if (this.ignoreEmptyBibliography && (await field.getText()).trim() === "") {
this._removeCodeFields[i] = true;
} else {
field.index = i;
@ -965,15 +979,15 @@ Zotero.Integration.Fields.prototype._processFields = Zotero.Promise.coroutine(fu
}
}
if (this._bibliographyFields.length) {
var data = yield this._bibliographyFields[0].unserialize()
this._session.bibliography = new Zotero.Integration.Bibliography(this._bibliographyFields[0], data);
yield this._session.bibliography.loadItemData();
var data = await this._bibliographyFields[0].unserialize()
this.bibliography = new Zotero.Integration.Bibliography(this._bibliographyFields[0], data);
await this.bibliography.loadItemData();
} else {
delete this._session.bibliography;
delete this.bibliography;
}
// TODO: figure this out
// Zotero.Notifier.trigger('add', 'collection', 'document');
});
};
/**
* Updates bibliographies and fields within a document
@ -983,31 +997,31 @@ Zotero.Integration.Fields.prototype._processFields = Zotero.Promise.coroutine(fu
* modified since they were created, instead of showing a warning
* @return {Promise} A promise resolved when the document is updated
*/
Zotero.Integration.Fields.prototype.updateDocument = Zotero.Promise.coroutine(function* (forceCitations, forceBibliography,
Zotero.Integration.Session.prototype.updateDocument = Zotero.Promise.coroutine(function* (forceCitations, forceBibliography,
ignoreCitationChanges) {
this._session.timer = new Zotero.Integration.Timer();
this._session.timer.start();
this.timer = new Zotero.Integration.Timer();
this.timer.start();
this._session.progressBar.start();
yield this._session._updateCitations()
this._session.progressBar.finishSegment();
this._session.progressBar.start();
this.progressBar.start();
yield this._updateCitations();
this.progressBar.finishSegment();
this.progressBar.start();
yield this._updateDocument(forceCitations, forceBibliography, ignoreCitationChanges)
this._session.progressBar.finishSegment();
this.progressBar.finishSegment();
var diff = this._session.timer.stop();
this._session.timer = null;
var diff = this.timer.stop();
this.timer = null;
Zotero.debug(`Integration: updateDocument complete in ${diff}s`)
// If the update takes longer than 5s suggest delaying citation updates
if (diff > DELAY_CITATIONS_PROMPT_TIMEOUT && !this._session.data.prefs.dontAskDelayCitationUpdates && !this._session.data.prefs.delayCitationUpdates) {
if (diff > DELAY_CITATIONS_PROMPT_TIMEOUT && !this.data.prefs.dontAskDelayCitationUpdates && !this._session.data.prefs.delayCitationUpdates) {
yield this._doc.activate();
var interfaceType = 'tab';
if (['MacWord2008', 'OpenOffice'].includes(this._session.agent)) {
if (['MacWord2008', 'OpenOffice'].includes(this.agent)) {
interfaceType = 'toolbar';
}
var result = yield this._session.displayAlert(
var result = yield this.displayAlert(
Zotero.getString('integration.delayCitationUpdates.alert.text1')
+ "\n\n"
+ Zotero.getString(`integration.delayCitationUpdates.alert.text2.${interfaceType}`)
@ -1017,11 +1031,11 @@ Zotero.Integration.Fields.prototype.updateDocument = Zotero.Promise.coroutine(fu
DIALOG_BUTTONS_YES_NO_CANCEL
);
if (result == 2) {
this._session.data.prefs.delayCitationUpdates = true;
this.data.prefs.delayCitationUpdates = true;
}
if (result) {
this._session.data.prefs.dontAskDelayCitationUpdates = true;
// yield this._session.setDocPrefs(true);
this.data.prefs.dontAskDelayCitationUpdates = true;
// yield this.setDocPrefs(true);
}
}
});
@ -1033,11 +1047,11 @@ Zotero.Integration.Fields.prototype.updateDocument = Zotero.Promise.coroutine(fu
* @param {Boolean} [ignoreCitationChanges] Whether to ignore changes to citations that have been
* modified since they were created, instead of showing a warning
*/
Zotero.Integration.Fields.prototype._updateDocument = async function(forceCitations, forceBibliography,
Zotero.Integration.Session.prototype._updateDocument = async function(forceCitations, forceBibliography,
ignoreCitationChanges) {
if(this.progressCallback) {
var nFieldUpdates = Object.keys(this._session.processIndices).length;
if(this._session.bibliographyHasChanged || forceBibliography) {
var nFieldUpdates = Object.keys(this.processIndices).length;
if(this.bibliographyHasChanged || forceBibliography) {
nFieldUpdates += this._bibliographyFields.length*5;
}
}
@ -1064,12 +1078,12 @@ Zotero.Integration.Fields.prototype._updateDocument = async function(forceCitati
// Although at least for macword you don't get to interact with the document
// while a prompt is being displayed, so the order of these prompts is to a large
// degree a minor issue.
var indicesToUpdate = Object.keys(this._session.processIndices);
var indicesToUpdate = Object.keys(this.processIndices);
// Add bibliography indices to the above indices
if (this._session.bibliography // if bibliography exists
&& Object.keys(this._session.citationsByIndex).length // and doc has citations
&& (this._session.bibliographyHasChanged // and bibliography changed
if (this.bibliography // if bibliography exists
&& Object.keys(this.citationsByIndex).length // and doc has citations
&& (this.bibliographyHasChanged // and bibliography changed
|| forceBibliography)) { // or if we should generate regardless of
// changes
for (let field of this._bibliographyFields) {
@ -1092,7 +1106,7 @@ Zotero.Integration.Fields.prototype._updateDocument = async function(forceCitati
// Jump to next event loop step for UI updates
await Zotero.Promise.delay();
var citation = this._session.citationsByIndex[i];
var citation = this.citationsByIndex[i];
if (citation) {
let citationField = citation._field;
@ -1111,7 +1125,7 @@ Zotero.Integration.Fields.prototype._updateDocument = async function(forceCitati
+ "Current: " + plainCitation
);
await citationField.select();
var result = await this._session.displayAlert(
var result = await this.displayAlert(
Zotero.getString("integration.citationChanged")+"\n\n"
+ Zotero.getString("integration.citationChanged.description")+"\n\n"
+ Zotero.getString("integration.citationChanged.original", citation.properties.plainCitation)+"\n"
@ -1121,7 +1135,7 @@ Zotero.Integration.Fields.prototype._updateDocument = async function(forceCitati
citation.properties.dontUpdate = true;
// Sigh. This hurts. setCode in LO forces a text reset. If the formattedText is rtf
// it is reinserted, however that breaks what properties.dontUpdate should do
if (this._session.primaryFieldType == "ReferenceMark"
if (this.primaryFieldType == "ReferenceMark"
&& citation.properties.formattedCitation.includes('\\')) {
citation.properties.formattedCitation = citation.properties.plainCitation;
}
@ -1141,7 +1155,7 @@ Zotero.Integration.Fields.prototype._updateDocument = async function(forceCitati
// for citations that were inserted with delay styling
var wasDelayed = citation.properties.formattedCitation
&& citation.properties.formattedCitation.includes(DELAYED_CITATION_RTF_STYLING);
if (this._session.outputFormat == 'rtf' && wasDelayed) {
if (this.outputFormat == 'rtf' && wasDelayed) {
isRich = await citationField.setText(`${DELAYED_CITATION_RTF_STYLING_CLEAR}{${formattedCitation}}`);
} else {
isRich = await citationField.setText(formattedCitation);
@ -1170,24 +1184,24 @@ Zotero.Integration.Fields.prototype._updateDocument = async function(forceCitati
throw new Error(`Attempting to update field ${i} which does not exist`);
}
if (forceBibliography || this._session.bibliographyDataHasChanged) {
let code = this._session.bibliography.serialize();
if (forceBibliography || this.bibliographyDataHasChanged) {
let code = this.bibliography.serialize();
await bibliographyField.setCode(code);
}
// get bibliography and format as RTF
var bib = this._session.bibliography.getCiteprocBibliography(this._session.style);
var bib = this.bibliography.getCiteprocBibliography(this.style);
var bibliographyText = "";
if (bib) {
if (this._session.outputFormat == 'rtf') {
if (this.outputFormat == 'rtf') {
bibliographyText = bib[0].bibstart+bib[1].join("\\\r\n")+"\\\r\n"+bib[0].bibend;
} else {
bibliographyText = bib[0].bibstart+bib[1].join("")+bib[0].bibend;
}
// if bibliography style not set, set it
if(!this._session.data.style.bibliographyStyleHasBeenSet) {
if(!this.data.style.bibliographyStyleHasBeenSet) {
var bibStyle = Zotero.Cite.getBibliographyFormatParameters(bib);
// set bibliography style
@ -1195,7 +1209,7 @@ Zotero.Integration.Fields.prototype._updateDocument = async function(forceCitati
bibStyle.lineSpacing, bibStyle.entrySpacing, bibStyle.tabStops, bibStyle.tabStops.length);
// set bibliographyStyleHasBeenSet parameter to prevent further changes
this._session.data.style.bibliographyStyleHasBeenSet = true;
this.data.style.bibliographyStyleHasBeenSet = true;
}
}
@ -1231,13 +1245,15 @@ Zotero.Integration.Fields.prototype._updateDocument = async function(forceCitati
for (var i=(deleteFields.length-1); i>=0; i--) {
this._fields[deleteFields[i]].delete();
}
this._session.processIndices = {}
this.processIndices = {}
}
/**
* Brings up the addCitationDialog, prepopulated if a citation is provided
* Insert a citation at cursor location or edit the existing one,
* display the citation dialog and perform any field/text inserts after
* the dialog edits are accepted
*/
Zotero.Integration.Fields.prototype.addEditCitation = async function (field) {
Zotero.Integration.Session.prototype.cite = async function (field) {
var newField;
var citation;
@ -1260,10 +1276,10 @@ Zotero.Integration.Fields.prototype.addEditCitation = async function (field) {
// Preparing data to pass into CitationEditInterface
var fieldIndexPromise, citationsByItemIDPromise;
if (!this._session.data.prefs.delayCitationUpdates
|| !Object.keys(this._session.citationsByItemID).length
|| this._session._sessionUpToDate) {
fieldIndexPromise = this.get().then(async function (fields) {
if (!this.data.prefs.delayCitationUpdates
|| !Object.keys(this.citationsByItemID).length
|| this._sessionUpToDate) {
fieldIndexPromise = this.getFields().then(async function (fields) {
for (var i = 0, n = fields.length; i < n; i++) {
if (await fields[i].equals(field._field)) {
// This is needed, because LibreOffice integration plugin caches the field code instead of asking
@ -1274,20 +1290,20 @@ Zotero.Integration.Fields.prototype.addEditCitation = async function (field) {
}
return -1;
});
citationsByItemIDPromise = this.updateSession(FORCE_CITATIONS_FALSE).then(function() {
return this._session.citationsByItemID;
citationsByItemIDPromise = this.updateFromDocument(FORCE_CITATIONS_FALSE).then(function() {
return this.citationsByItemID;
}.bind(this));
}
else {
fieldIndexPromise = Zotero.Promise.resolve(-1);
citationsByItemIDPromise = Zotero.Promise.resolve(this._session.citationsByItemID);
citationsByItemIDPromise = Zotero.Promise.resolve(this.citationsByItemID);
}
var previewFn = async function (citation) {
let idx = await fieldIndexPromise;
await citationsByItemIDPromise;
var [citations, fieldToCitationIdxMapping, citationToFieldIdxMapping] = this._session.getCiteprocLists();
var [citations, fieldToCitationIdxMapping, citationToFieldIdxMapping] = this.getCiteprocLists();
for (var prevIdx = idx-1; prevIdx >= 0; prevIdx--) {
if (prevIdx in fieldToCitationIdxMapping) break;
}
@ -1299,7 +1315,7 @@ Zotero.Integration.Fields.prototype.addEditCitation = async function (field) {
let citationsPost = citations.slice(sliceIdx);
let citationID = citation.citationID;
try {
var result = this._session.style.previewCitationCluster(citation, citationsPre, citationsPost, "rtf");
var result = this.style.previewCitationCluster(citation, citationsPre, citationsPost, "rtf");
} catch(e) {
throw e;
} finally {
@ -1311,7 +1327,7 @@ Zotero.Integration.Fields.prototype.addEditCitation = async function (field) {
}.bind(this);
var io = new Zotero.Integration.CitationEditInterface(
citation, this._session.style.opt.sort_citations,
citation, this.style.opt.sort_citations,
fieldIndexPromise, citationsByItemIDPromise, previewFn
);
Zotero.debug(`Editing citation:`);
@ -1425,25 +1441,6 @@ Zotero.Integration.CitationEditInterface.prototype = {
},
}
/**
* Keeps track of all session-specific variables
*/
Zotero.Integration.Session = function(doc, app) {
this.embeddedItems = {};
this.embeddedZoteroItems = {};
this.embeddedItemsByURI = {};
this.citationsByIndex = {};
this.resetRequest(doc);
this.primaryFieldType = app.primaryFieldType;
this.secondaryFieldType = app.secondaryFieldType;
this.outputFormat = app.outputFormat || 'rtf';
this._sessionUpToDate = false;
this._app = app;
this.sessionID = Zotero.randomString();
Zotero.Integration.sessions[this.sessionID] = this;
}
/**
* Resets per-request variables in the CitationSet
*/
@ -1459,7 +1456,7 @@ Zotero.Integration.Session.prototype.resetRequest = function(doc) {
this.oldCitations = new Set();
for (let i in this.citationsByIndex) {
// But ignore indices from this.newIndices. If any are present it means that the last
// call to this.updateSession() was never followed up with this.updateDocument()
// call to this.updateFromDocument() was never followed up with this.updateDocument()
// i.e. the operation was user cancelled
if (i in this.newIndices) continue;
this.oldCitations.add(this.citationsByIndex[i].citationID);
@ -1579,7 +1576,7 @@ Zotero.Integration.Session.prototype.setData = async function (data, resetStyle)
* if there wasn't, or rejected with Zotero.Exception.UserCancelled if the dialog was
* cancelled.
*/
Zotero.Integration.Session.prototype.setDocPrefs = Zotero.Promise.coroutine(function* (showImportExport=false) {
Zotero.Integration.Session.prototype.setDocPrefs = async function (showImportExport=false) {
var io = new function() { this.wrappedJSObject = this; };
io.primaryFieldType = this.primaryFieldType;
io.secondaryFieldType = this.secondaryFieldType;
@ -1599,8 +1596,8 @@ Zotero.Integration.Session.prototype.setDocPrefs = Zotero.Promise.coroutine(func
}
// Make sure styles are initialized for new docs
yield Zotero.Styles.init();
yield Zotero.Integration.displayDialog('chrome://zotero/content/integration/integrationDocPrefs.xul', '', io);
await Zotero.Styles.init();
await Zotero.Integration.displayDialog('chrome://zotero/content/integration/integrationDocPrefs.xul', '', io);
if (io.exportDocument) {
return this.exportDocument();
@ -1628,7 +1625,7 @@ Zotero.Integration.Session.prototype.setDocPrefs = Zotero.Promise.coroutine(func
oldData.prefs.automaticJournalAbbreviations != data.prefs.automaticJournalAbbreviations
|| oldData.style.locale != io.locale
);
yield this.setData(data, forceStyleReset);
await this.setData(data, forceStyleReset);
// need to do this after setting the data so that we know if it's a note style
this.data.prefs.noteType = this.style && this.styleClass == "note" ? io.useEndnotes+1 : 0;
@ -1644,7 +1641,7 @@ Zotero.Integration.Session.prototype.setDocPrefs = Zotero.Promise.coroutine(func
}
return oldData || null;
})
}
Zotero.Integration.Session.prototype.exportDocument = async function() {
Zotero.debug("Integration: Exporting the document");
@ -1704,13 +1701,13 @@ Zotero.Integration.Session.prototype.importDocument = async function() {
var data = new Zotero.Integration.DocumentData(await this._doc.getDocumentData());
data.prefs.fieldType = this._app.primaryFieldType;
await this.setData(data, true);
await this.fields.get(true);
await this.fields.updateSession(FORCE_CITATIONS_RESET_TEXT);
await this.getFields(true);
await this.updateFromDocument(FORCE_CITATIONS_RESET_TEXT);
// Make sure we ignore the dont update flags since we do not know what the original text was
for (let index in this.citationsByIndex) {
delete this.citationsByIndex[index].properties.dontUpdate;
}
await this.fields.updateDocument(FORCE_CITATIONS_RESET_TEXT, true, true);
await this.updateDocument(FORCE_CITATIONS_RESET_TEXT, true, true);
} finally {
Zotero.debug(`Integration: Import finished in ${timer.stop()}`);
}
@ -1727,18 +1724,18 @@ Zotero.Integration.Session.prototype.addCitation = Zotero.Promise.coroutine(func
if (action == Zotero.Integration.REMOVE_CODE) {
// Mark for removal and return
this.fields._removeCodeFields[index] = true;
this._removeCodeFields[index] = true;
return;
} else if (action == Zotero.Integration.DELETE) {
// Mark for deletion and return
this.fields._deleteFields[index] = true;
this._deleteFields[index] = true;
return;
} else if (action == Zotero.Integration.UPDATE) {
this.updateIndices[index] = true;
}
// All new fields will initially be marked for deletion because they contain no
// citationItems
delete this.fields._deleteFields[index];
delete this._deleteFields[index];
citation.properties.zoteroIndex = index;
citation.properties.noteIndex = noteIndex;
@ -1773,10 +1770,8 @@ Zotero.Integration.Session.prototype.addCitation = Zotero.Promise.coroutine(func
// and either one may need to be updated
this.newIndices[duplicateIndex] = true;
}
if (needNewID) {
Zotero.debug("Integration: "+citation.citationID+" ("+index+") needs new citationID");
citation.citationID = Zotero.Utilities.randomString();
}
this.newIndices[index] = true;
}
// Deal with citations that are copied into the document from somewhere else
@ -1859,7 +1854,7 @@ Zotero.Integration.Session.prototype._updateCitations = async function () {
* Restores processor state from document, without requesting citation updates
*/
Zotero.Integration.Session.prototype.restoreProcessorState = function() {
if (this.fields._bibliographyFields.length && !this.bibliography) {
if (this._bibliographyFields.length && !this.bibliography) {
throw new Error ("Attempting to restore processor state without loading bibliography");
}
let uncited = [];
@ -1915,7 +1910,7 @@ Zotero.Integration.Session.prototype.writeDelayedCitation = Zotero.Promise.corou
// Note: fields._fields will only contain items upon first delayed insert
// after a full update
if (this._sessionUpToDate) {
var fields = yield this.fields.get();
var fields = yield this.getFields();
for (let i = fields.length - 1; i >= 0; i--) {
let field = yield Zotero.Integration.Field.loadExisting(fields[i]);
if (field.type == INTEGRATION_TYPE_BIBLIOGRAPHY) {
@ -2573,9 +2568,6 @@ Zotero.Integration.CitationField = class extends Zotero.Integration.Field {
} else if (result == 1) { // No
return false;
} else { // Yes
var fieldGetter = Zotero.Integration.currentSession.fields,
oldWindow = Zotero.Integration.currentWindow,
oldProgressCallback = this.progressCallback;
// Clear current code and subsequent addEditCitation dialog will be the reselection
await this.clearCode();
return this.unserialize();

View file

@ -692,12 +692,12 @@ describe("Zotero.Integration", function () {
doc.fields[1].code = doc.fields[0].code;
doc.fields[1].text = doc.fields[0].text;
var originalUpdateDocument = Zotero.Integration.Fields.prototype.updateDocument;
var stubUpdateDocument = sinon.stub(Zotero.Integration.Fields.prototype, 'updateDocument');
var originalUpdateDocument = Zotero.Integration.Session.prototype.updateDocument;
var stubUpdateDocument = sinon.stub(Zotero.Integration.Session.prototype, 'updateDocument');
try {
var indicesLength;
stubUpdateDocument.callsFake(function() {
indicesLength = Object.keys(Zotero.Integration.currentSession.newIndices).length;
indicesLength = Object.keys(this.newIndices).length;
return originalUpdateDocument.apply(this, arguments);
});
@ -726,12 +726,12 @@ describe("Zotero.Integration", function () {
`"citationID":"${newCitationID}"`);
doc.fields[1].text = doc.fields[0].text;
var originalUpdateDocument = Zotero.Integration.Fields.prototype.updateDocument;
var stubUpdateDocument = sinon.stub(Zotero.Integration.Fields.prototype, 'updateDocument');
var originalUpdateDocument = Zotero.Integration.Session.prototype.updateDocument;
var stubUpdateDocument = sinon.stub(Zotero.Integration.Session.prototype, 'updateDocument');
try {
var indices;
stubUpdateDocument.callsFake(function() {
indices = Object.keys(Zotero.Integration.currentSession.newIndices);
indices = Object.keys(this.newIndices);
return originalUpdateDocument.apply(this, arguments);
});