fx-compat: RemoteTranslate improvements

- Support removeHandler()
- Return DB items from translate() when called with libraryID
- Don't invoke done until attachments are done

Fixes #3084 ("after all" hook still times out, but that happens even if the test
is disabled)
This commit is contained in:
Abe Jellinek 2023-04-17 16:20:54 -04:00
parent 096a3c5f2f
commit b222bbcccb
3 changed files with 64 additions and 17 deletions

View file

@ -53,8 +53,8 @@ class RemoteTranslate {
_wasSuccess = false;
constructor() {
TranslationManager.add(this._id);
TranslationManager.setHandler(this._id, 'done', success => this._wasSuccess = success);
TranslationManager.add(this._id, this);
TranslationManager.setHandler(this._id, 'done', (_, success) => this._wasSuccess = success);
}
/**
@ -86,7 +86,23 @@ class RemoteTranslate {
this._doneHandlers.push(handler);
}
else {
TranslationManager.setHandler(this._id, name, (...args) => handler(this, ...args));
TranslationManager.setHandler(this._id, name, handler);
}
}
/**
* Remove a handler added by #setHandler().
*
* @param {String} name
* @param {Function} handler
*/
removeHandler(name, handler) {
// 'done' is triggered from translate()
if (name == 'done') {
this._doneHandlers = this._doneHandlers.filter(h => h !== handler);
}
else {
TranslationManager.removeHandler(this._id, name, handler);
}
}
@ -141,10 +157,13 @@ class RemoteTranslate {
*/
async translate(options = {}) {
let actor = this._browser.browsingContext.currentWindowGlobal.getActor("Translation");
let items = null;
let items = [];
try {
items = await actor.sendQuery("translate", { translator: this._translator, id: this._id });
let jsonItems = await actor.sendQuery("translate", { translator: this._translator, id: this._id });
if (options.libraryID !== false) {
let itemsLeftToSave = jsonItems.length;
let attachmentsInProgress = new Set();
let doneHandlersInvoked = false;
let itemSaver = new Zotero.Translate.ItemSaver({
libraryID: options.libraryID,
collections: options.collections,
@ -154,22 +173,43 @@ class RemoteTranslate {
// proxy: unimplemented in the client
});
// Call itemDone on each completed item
let invokeDoneHandlersIfDone = () => {
if (itemsLeftToSave || attachmentsInProgress.size || doneHandlersInvoked) {
return;
}
// Call done (saved in #setHandler() above) at the end
// The Zotero.Translate instance running in the content process has already tried to call done by now,
// but we prevented it from reaching the caller. Now that we've run ItemSaver#saveItems() on this side,
// we can pass it through.
this._callDoneHandlers(this._wasSuccess);
doneHandlersInvoked = true;
};
let itemsDoneCallback = (jsonItems, dbItems) => {
for (let i = 0; i < jsonItems.length; i++) {
// Call itemDone on each completed item
for (let i = 0; i < dbItems.length; i++) {
let jsonItem = jsonItems[i];
let dbItem = dbItems[i];
TranslationManager.runHandler(this._id, 'itemDone', dbItem, jsonItem);
}
items.push(...dbItems);
itemsLeftToSave -= dbItems.length;
invokeDoneHandlersIfDone();
};
await itemSaver.saveItems(items, () => {}, itemsDoneCallback);
let attachmentCallback = (attachment, progress) => {
if (progress === 100 || progress === false) {
attachmentsInProgress.delete(attachment);
}
else {
attachmentsInProgress.add(attachment);
}
invokeDoneHandlersIfDone();
};
await itemSaver.saveItems(jsonItems, attachmentCallback, itemsDoneCallback);
}
else {
items.push(...jsonItems);
}
// And call done (saved in #setHandler() above) at the end
// The Zotero.Translate instance running in the content process has already tried to call done by now,
// but we prevented it from reaching the caller. Now that we've run ItemSaver#saveItems() on this side,
// we can pass it through.
this._callDoneHandlers(this._wasSuccess);
}
catch (e) {
this._callDoneHandlers(false);

View file

@ -7,8 +7,9 @@ const Zotero = Components.classes['@zotero.org/Zotero;1']
const TranslationManager = new class {
_registeredRemoteTranslates = new Map();
add(id) {
add(id, remoteTranslate) {
this._registeredRemoteTranslates.set(id, {
remoteTranslate,
translatorProvider: null,
handlers: {},
});
@ -37,18 +38,24 @@ const TranslationManager = new class {
this._registeredRemoteTranslates.get(id).handlers[name] = [handler];
}
}
removeHandler(id, name, handler) {
this._registeredRemoteTranslates.get(id).handlers[name]
= this._registeredRemoteTranslates.get(id).handlers[name].filter(h => h !== handler);
}
clearHandlers(id, name) {
this._registeredRemoteTranslates.get(id).handlers[name] = null;
}
async runHandler(id, name, ...args) {
let remoteTranslate = this._registeredRemoteTranslates.get(id).remoteTranslate;
let handlers = this._registeredRemoteTranslates.get(id).handlers[name];
let returnValue = null;
if (handlers) {
for (let handler of handlers) {
try {
returnValue = await handler(...args);
returnValue = await handler(remoteTranslate, ...args);
}
catch (e) {
Zotero.logError(e);

View file

@ -849,7 +849,7 @@ Zotero.Attachments = new function(){
* @return {Promise<Zotero.Item>} - A promise for the created attachment item
*/
this.importFromDocument = Zotero.Promise.coroutine(function* (options) {
Zotero.debug('Importing attachment from document');
Zotero.debug('Importing attachment from ' + (options.document ? 'document' : 'browser'));
var libraryID = options.libraryID;
var document = options.document;