mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-19 22:58:07 +02:00
Merge pull request #18573 from calixteman/cancel_ai_requests
[Editor] Dispatch changes in prefs enableAltTextModelDownload and enableGuessAltText to the viewer (bug 1912024)
This commit is contained in:
commit
fef2853263
6 changed files with 164 additions and 53 deletions
|
@ -141,9 +141,11 @@ class StampEditor extends AnnotationEditor {
|
|||
this._uiManager.useNewAltTextFlow &&
|
||||
this.#bitmap
|
||||
) {
|
||||
// The alt-text dialog isn't opened but we still want to guess the alt
|
||||
// text.
|
||||
this.mlGuessAltText();
|
||||
try {
|
||||
// The alt-text dialog isn't opened but we still want to guess the alt
|
||||
// text.
|
||||
this.mlGuessAltText();
|
||||
} catch {}
|
||||
}
|
||||
|
||||
this.div.focus();
|
||||
|
@ -155,8 +157,11 @@ class StampEditor extends AnnotationEditor {
|
|||
}
|
||||
|
||||
const { mlManager } = this._uiManager;
|
||||
if (!mlManager || !(await mlManager.isEnabledFor("altText"))) {
|
||||
return null;
|
||||
if (!mlManager) {
|
||||
throw new Error("No ML.");
|
||||
}
|
||||
if (!(await mlManager.isEnabledFor("altText"))) {
|
||||
throw new Error("ML isn't enabled for alt text.");
|
||||
}
|
||||
const { data, width, height } =
|
||||
imageData ||
|
||||
|
@ -170,9 +175,18 @@ class StampEditor extends AnnotationEditor {
|
|||
channels: data.length / (width * height),
|
||||
},
|
||||
});
|
||||
if (!response || response.error || !response.output) {
|
||||
if (!response) {
|
||||
throw new Error("No response from the AI service.");
|
||||
}
|
||||
if (response.error) {
|
||||
throw new Error("Error from the AI service.");
|
||||
}
|
||||
if (response.cancel) {
|
||||
return null;
|
||||
}
|
||||
if (!response.output) {
|
||||
throw new Error("No valid response from the AI service.");
|
||||
}
|
||||
const altText = response.output;
|
||||
await this.setGuessedAltText(altText);
|
||||
if (updateAltTextData && !this.hasAltTextData()) {
|
||||
|
|
|
@ -404,9 +404,7 @@ const PDFViewerApplication = {
|
|||
} else {
|
||||
eventBus = new EventBus();
|
||||
}
|
||||
if (this.mlManager) {
|
||||
this.mlManager.eventBus = eventBus;
|
||||
}
|
||||
this.mlManager?.setEventBus(eventBus, this._globalAbortController.signal);
|
||||
this.eventBus = eventBus;
|
||||
|
||||
this.overlayManager = new OverlayManager();
|
||||
|
|
|
@ -193,12 +193,12 @@ const defaultOptions = {
|
|||
enableAltTextModelDownload: {
|
||||
/** @type {boolean} */
|
||||
value: true,
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE + OptionKind.EVENT_DISPATCH,
|
||||
},
|
||||
enableGuessAltText: {
|
||||
/** @type {boolean} */
|
||||
value: true,
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
|
||||
kind: OptionKind.VIEWER + OptionKind.PREFERENCE + OptionKind.EVENT_DISPATCH,
|
||||
},
|
||||
enableHighlightEditor: {
|
||||
// We'll probably want to make some experiments before enabling this
|
||||
|
|
|
@ -307,11 +307,15 @@ class FirefoxScripting {
|
|||
}
|
||||
|
||||
class MLManager {
|
||||
#abortSignal = null;
|
||||
|
||||
#enabled = null;
|
||||
|
||||
#eventBus = null;
|
||||
|
||||
#ready = null;
|
||||
|
||||
eventBus = null;
|
||||
#requestResolvers = null;
|
||||
|
||||
hasProgress = false;
|
||||
|
||||
|
@ -330,6 +334,32 @@ class MLManager {
|
|||
this.enableGuessAltText = enableGuessAltText;
|
||||
}
|
||||
|
||||
setEventBus(eventBus, abortSignal) {
|
||||
this.#eventBus = eventBus;
|
||||
this.#abortSignal = abortSignal;
|
||||
eventBus._on(
|
||||
"enablealttextmodeldownload",
|
||||
({ value }) => {
|
||||
if (this.enableAltTextModelDownload === value) {
|
||||
return;
|
||||
}
|
||||
if (value) {
|
||||
this.downloadModel("altText");
|
||||
} else {
|
||||
this.deleteModel("altText");
|
||||
}
|
||||
},
|
||||
abortSignal
|
||||
);
|
||||
eventBus._on(
|
||||
"enableguessalttext",
|
||||
({ value }) => {
|
||||
this.toggleService("altText", value);
|
||||
},
|
||||
abortSignal
|
||||
);
|
||||
}
|
||||
|
||||
async isEnabledFor(name) {
|
||||
return this.enableGuessAltText && !!(await this.#enabled?.get(name));
|
||||
}
|
||||
|
@ -339,16 +369,17 @@ class MLManager {
|
|||
}
|
||||
|
||||
async deleteModel(name) {
|
||||
if (name !== "altText") {
|
||||
if (name !== "altText" || !this.enableAltTextModelDownload) {
|
||||
return;
|
||||
}
|
||||
this.enableAltTextModelDownload = false;
|
||||
this.#ready?.delete(name);
|
||||
this.#enabled?.delete(name);
|
||||
await Promise.all([
|
||||
this.toggleService("altText", false),
|
||||
FirefoxCom.requestAsync("mlDelete", MLManager.#AI_ALT_TEXT_MODEL_NAME),
|
||||
]);
|
||||
await this.toggleService("altText", false);
|
||||
await FirefoxCom.requestAsync(
|
||||
"mlDelete",
|
||||
MLManager.#AI_ALT_TEXT_MODEL_NAME
|
||||
);
|
||||
}
|
||||
|
||||
async loadModel(name) {
|
||||
|
@ -358,7 +389,7 @@ class MLManager {
|
|||
}
|
||||
|
||||
async downloadModel(name) {
|
||||
if (name !== "altText") {
|
||||
if (name !== "altText" || this.enableAltTextModelDownload) {
|
||||
return null;
|
||||
}
|
||||
this.enableAltTextModelDownload = true;
|
||||
|
@ -369,18 +400,53 @@ class MLManager {
|
|||
if (data?.name !== "altText") {
|
||||
return null;
|
||||
}
|
||||
const resolvers = (this.#requestResolvers ||= new Set());
|
||||
const resolver = Promise.withResolvers();
|
||||
resolvers.add(resolver);
|
||||
|
||||
data.service = MLManager.#AI_ALT_TEXT_MODEL_NAME;
|
||||
return FirefoxCom.requestAsync("mlGuess", data);
|
||||
const requestPromise = FirefoxCom.requestAsync("mlGuess", data);
|
||||
|
||||
requestPromise
|
||||
.then(response => {
|
||||
if (resolvers.has(resolver)) {
|
||||
resolver.resolve(response);
|
||||
resolvers.delete(resolver);
|
||||
}
|
||||
})
|
||||
.catch(reason => {
|
||||
if (resolvers.has(resolver)) {
|
||||
resolver.reject(reason);
|
||||
resolvers.delete(resolver);
|
||||
}
|
||||
});
|
||||
|
||||
return resolver.promise;
|
||||
}
|
||||
|
||||
async #cancelAllRequests() {
|
||||
if (!this.#requestResolvers) {
|
||||
return;
|
||||
}
|
||||
for (const resolver of this.#requestResolvers) {
|
||||
resolver.resolve({ cancel: true });
|
||||
}
|
||||
this.#requestResolvers.clear();
|
||||
this.#requestResolvers = null;
|
||||
}
|
||||
|
||||
async toggleService(name, enabled) {
|
||||
if (name !== "altText") {
|
||||
if (name !== "altText" || this.enableGuessAltText === enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.enableGuessAltText = enabled;
|
||||
if (enabled && this.enableAltTextModelDownload) {
|
||||
await this.#loadAltTextEngine(false);
|
||||
if (enabled) {
|
||||
if (this.enableAltTextModelDownload) {
|
||||
await this.#loadAltTextEngine(false);
|
||||
}
|
||||
} else {
|
||||
this.#cancelAllRequests();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,7 +469,7 @@ class MLManager {
|
|||
if (listenToProgress) {
|
||||
this.hasProgress = true;
|
||||
const callback = ({ detail }) => {
|
||||
this.eventBus.dispatch("loadaiengineprogress", {
|
||||
this.#eventBus.dispatch("loadaiengineprogress", {
|
||||
source: this,
|
||||
detail,
|
||||
});
|
||||
|
@ -412,7 +478,9 @@ class MLManager {
|
|||
window.removeEventListener("loadAIEngineProgress", callback);
|
||||
}
|
||||
};
|
||||
window.addEventListener("loadAIEngineProgress", callback);
|
||||
window.addEventListener("loadAIEngineProgress", callback, {
|
||||
signal: this.#abortSignal,
|
||||
});
|
||||
promise.then(ok => {
|
||||
if (!ok) {
|
||||
this.hasProgress = false;
|
||||
|
|
|
@ -79,6 +79,10 @@ class FakeMLManager {
|
|||
this.enableAltTextModelDownload = enableAltTextModelDownload;
|
||||
}
|
||||
|
||||
setEventBus(eventBus, abortSignal) {
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
|
||||
async isEnabledFor(_name) {
|
||||
return this.enableGuessAltText;
|
||||
}
|
||||
|
|
|
@ -137,6 +137,10 @@ class NewAltTextManager {
|
|||
this.#toggleDisclaimer();
|
||||
});
|
||||
|
||||
eventBus._on("enableguessalttext", ({ value }) => {
|
||||
this.#toggleGuessAltText(value, /* isInitial = */ false);
|
||||
});
|
||||
|
||||
this.#overlayManager.register(dialog);
|
||||
}
|
||||
|
||||
|
@ -247,13 +251,12 @@ class NewAltTextManager {
|
|||
this.#imageData,
|
||||
/* updateAltTextData = */ false
|
||||
);
|
||||
if (altText === null) {
|
||||
throw new Error("No valid response from the AI service.");
|
||||
}
|
||||
this.#guessedAltText = altText;
|
||||
this.#wasAILoading = this.#isAILoading;
|
||||
if (this.#isAILoading) {
|
||||
this.#addAltText(altText);
|
||||
if (altText) {
|
||||
this.#guessedAltText = altText;
|
||||
this.#wasAILoading = this.#isAILoading;
|
||||
if (this.#isAILoading) {
|
||||
this.#addAltText(altText);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
@ -458,6 +461,8 @@ class ImageAltTextSettings {
|
|||
|
||||
#createModelButton;
|
||||
|
||||
#downloadModelButton;
|
||||
|
||||
#dialog;
|
||||
|
||||
#eventBus;
|
||||
|
@ -486,6 +491,7 @@ class ImageAltTextSettings {
|
|||
this.#dialog = dialog;
|
||||
this.#aiModelSettings = aiModelSettings;
|
||||
this.#createModelButton = createModelButton;
|
||||
this.#downloadModelButton = downloadModelButton;
|
||||
this.#showAltTextDialogButton = showAltTextDialogButton;
|
||||
this.#overlayManager = overlayManager;
|
||||
this.#eventBus = eventBus;
|
||||
|
@ -508,40 +514,61 @@ class ImageAltTextSettings {
|
|||
this.#togglePref.bind(this, "enableNewAltTextWhenAddingImage")
|
||||
);
|
||||
|
||||
deleteModelButton.addEventListener("click", async () => {
|
||||
await mlManager.deleteModel("altText");
|
||||
deleteModelButton.addEventListener("click", this.#delete.bind(this, true));
|
||||
downloadModelButton.addEventListener(
|
||||
"click",
|
||||
this.#download.bind(this, true)
|
||||
);
|
||||
|
||||
aiModelSettings.classList.toggle("download", true);
|
||||
createModelButton.disabled = true;
|
||||
createModelButton.setAttribute("aria-pressed", false);
|
||||
this.#setPref("enableGuessAltText", false);
|
||||
this.#setPref("enableAltTextModelDownload", false);
|
||||
closeButton.addEventListener("click", this.#finish.bind(this));
|
||||
|
||||
eventBus._on("enablealttextmodeldownload", ({ value }) => {
|
||||
if (value) {
|
||||
this.#download(false);
|
||||
} else {
|
||||
this.#delete(false);
|
||||
}
|
||||
});
|
||||
|
||||
downloadModelButton.addEventListener("click", async () => {
|
||||
downloadModelButton.disabled = true;
|
||||
downloadModelButton.firstChild.setAttribute(
|
||||
this.#overlayManager.register(dialog);
|
||||
}
|
||||
|
||||
async #download(isFromUI = false) {
|
||||
if (isFromUI) {
|
||||
this.#downloadModelButton.disabled = true;
|
||||
this.#downloadModelButton.firstChild.setAttribute(
|
||||
"data-l10n-id",
|
||||
"pdfjs-editor-alt-text-settings-downloading-model-button"
|
||||
);
|
||||
|
||||
await mlManager.downloadModel("altText");
|
||||
await this.#mlManager.downloadModel("altText");
|
||||
|
||||
aiModelSettings.classList.toggle("download", false);
|
||||
downloadModelButton.firstChild.setAttribute(
|
||||
this.#downloadModelButton.firstChild.setAttribute(
|
||||
"data-l10n-id",
|
||||
"pdfjs-editor-alt-text-settings-download-model-button"
|
||||
);
|
||||
createModelButton.disabled = false;
|
||||
createModelButton.setAttribute("aria-pressed", true);
|
||||
this.#setPref("enableGuessAltText", true);
|
||||
mlManager.toggleService("altText", true);
|
||||
this.#setPref("enableAltTextModelDownload", true);
|
||||
downloadModelButton.disabled = false;
|
||||
});
|
||||
|
||||
closeButton.addEventListener("click", this.#finish.bind(this));
|
||||
this.#overlayManager.register(dialog);
|
||||
this.#createModelButton.disabled = false;
|
||||
this.#setPref("enableGuessAltText", true);
|
||||
this.#mlManager.toggleService("altText", true);
|
||||
this.#setPref("enableAltTextModelDownload", true);
|
||||
this.#downloadModelButton.disabled = false;
|
||||
}
|
||||
|
||||
this.#aiModelSettings.classList.toggle("download", false);
|
||||
this.#createModelButton.setAttribute("aria-pressed", true);
|
||||
}
|
||||
|
||||
async #delete(isFromUI = false) {
|
||||
if (isFromUI) {
|
||||
await this.#mlManager.deleteModel("altText");
|
||||
this.#setPref("enableGuessAltText", false);
|
||||
this.#setPref("enableAltTextModelDownload", false);
|
||||
}
|
||||
|
||||
this.#aiModelSettings.classList.toggle("download", true);
|
||||
this.#createModelButton.disabled = true;
|
||||
this.#createModelButton.setAttribute("aria-pressed", false);
|
||||
}
|
||||
|
||||
async open({ enableGuessAltText, enableNewAltTextWhenAddingImage }) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue