Gtranslate queue

This commit is contained in:
a 2020-08-12 00:20:46 +02:00
parent d5092e4ac0
commit 57ec8ac956
2 changed files with 53 additions and 18 deletions

View file

@ -7,7 +7,8 @@ import content_script from "../frontend/content_script/content_script.ts?file";
let com = new Communicator();
const scraper = new GTranslateScraper();
com.translateCallback = (toTranslate) => scraper.translate(toTranslate);
com.translateCallback = (toTranslate, sender) =>
scraper.translate(toTranslate, sender.tab?.id);
const db = new Flashcards();
com.addFlashcardCallback = (c) => db.addFlashcard(c);

View file

@ -1,23 +1,29 @@
import { browser, WebRequest, Runtime } from "webextension-polyfill-ts";
import content_script from "./gtranslate_content_script.ts?file";
interface TranslationRequest {
tabID?: number;
resolveFn: (value: Translation) => void;
rejectFn: (reason: String) => void;
toTranslate: string;
}
export class GTranslateScraper {
iframe: HTMLIFrameElement;
conn?: Runtime.Port;
resolveFn?: (value: Translation) => void;
rejectFn?: (reason: String) => void;
private conn?: Runtime.Port;
private current?: TranslationRequest;
private queue: Array<TranslationRequest> = [];
constructor() {
browser.runtime.onConnect.addListener((p) => {
if (p.name != "gtranslate_scraper_conn") return;
this.conn = p;
this.processFromQueue(p);
p.onMessage.addListener((m) => this.onTranslationRecieved(m));
});
//This allows us to create the google translate iframe by removing the x-frame-options header
browser.webRequest.onHeadersReceived.addListener(
allowIFrameAccess,
{
urls: ["<all_urls>"],
types: ["sub_frame"],
@ -28,7 +34,6 @@ export class GTranslateScraper {
//TODO make the language customizable
iframe.src = "https://translate.google.com/?op=translate&sl=de&tl=en";
this.iframe = iframe;
//Registers a temp content script, because we cannot inject scripts into iframes created on the background html page, because they have no tabId
const js = {
@ -46,21 +51,50 @@ export class GTranslateScraper {
document.body.appendChild(iframe);
});
}
onTranslationRecieved(message: Translation) {
if (this.resolveFn) this.resolveFn(message);
this.resolveFn = undefined;
this.rejectFn = undefined;
private onTranslationRecieved(message: Translation) {
if (this.current) this.current.resolveFn(message);
this.current = undefined;
this.processFromQueue(this.conn!);
}
translate(to_translate: string): Promise<Translation> {
if (this.rejectFn) this.rejectFn("Got a different translation request");
if (!this.conn) return Promise.reject("The translator is not yet ready");
private processTranslationRequest(
request: TranslationRequest,
conn: Runtime.Port
) {
this.current = request;
conn.postMessage(request.toTranslate);
}
this.conn.postMessage(to_translate);
return new Promise((resolve, reject) => {
this.resolveFn = resolve;
this.rejectFn = reject;
private processFromQueue(conn: Runtime.Port) {
const next = this.queue.pop();
if (next) this.processTranslationRequest(next, conn);
}
translate(to_translate: string, tabID?: number): Promise<Translation> {
if (to_translate == "") return Promise.resolve({ src: "", result: "" });
const p = new Promise((resolve: (value: Translation) => void, reject) => {
const req = {
toTranslate: to_translate,
resolveFn: resolve,
rejectFn: reject,
tabID: tabID,
};
if (this.current || !this.conn) {
//Remove the requests from the same tab
if (tabID)
this.queue = this.queue.filter((r) => {
if (r.tabID !== tabID) {
r.rejectFn("Got another request from the same tab");
return true;
}
});
this.queue.push(req);
} else {
this.processTranslationRequest(req, this.conn);
}
});
return p;
}
}