Strict ts mode
This commit is contained in:
parent
fdf8cbe0ff
commit
2f8d94bb1a
10 changed files with 98 additions and 85 deletions
|
@ -9,16 +9,17 @@ const scraper = new GTranslateScraper();
|
||||||
com.translateCallback = (toTranslate) => scraper.translate(toTranslate);
|
com.translateCallback = (toTranslate) => scraper.translate(toTranslate);
|
||||||
|
|
||||||
const db = new Flashcards();
|
const db = new Flashcards();
|
||||||
com.addFlashcardCallback = (card) => db.addFlashcard(card);
|
com.addFlashcardCallback = db.addFlashcard;
|
||||||
com.removeFlashcardCallback = (card) => console.log(db);
|
com.removeFlashcardCallback = db.removeFlashcard;
|
||||||
|
console.log(db);
|
||||||
|
|
||||||
const getTab = async (s: Runtime.MessageSender): Promise<Tabs.Tab> => {
|
const getTabID = async (s: Runtime.MessageSender): Promise<number> => {
|
||||||
if (s.tab) return s.tab;
|
if (s.tab?.id) return s.tab.id;
|
||||||
let tabs = await browser.tabs.query({
|
let tabs = await browser.tabs.query({
|
||||||
active: true,
|
active: true,
|
||||||
currentWindow: true,
|
currentWindow: true,
|
||||||
});
|
});
|
||||||
return tabs[0];
|
return tabs[0].id!;
|
||||||
};
|
};
|
||||||
|
|
||||||
const isEnabledSession = async (tabID: number): Promise<boolean> =>
|
const isEnabledSession = async (tabID: number): Promise<boolean> =>
|
||||||
|
@ -39,15 +40,15 @@ const injectScript = async (tabID: number, enabled?: boolean) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
com.setEnabledCallback = async (v: boolean, s: Runtime.MessageSender) => {
|
com.setEnabledCallback = async (v: boolean, s: Runtime.MessageSender) => {
|
||||||
const tab = await getTab(s);
|
const tab = await getTabID(s);
|
||||||
|
|
||||||
injectScript(tab.id);
|
injectScript(tab);
|
||||||
await setEnabledSession(tab.id, v);
|
await setEnabledSession(tab, v);
|
||||||
};
|
};
|
||||||
|
|
||||||
com.getEnabledCallback = async (s: Runtime.MessageSender): Promise<boolean> => {
|
com.getEnabledCallback = async (s: Runtime.MessageSender): Promise<boolean> => {
|
||||||
const tab = await getTab(s);
|
const tab = await getTabID(s);
|
||||||
return isEnabledSession(tab.id);
|
return isEnabledSession(tab);
|
||||||
};
|
};
|
||||||
|
|
||||||
browser.tabs.onUpdated.addListener(async (tabID, changeInfo) => {
|
browser.tabs.onUpdated.addListener(async (tabID, changeInfo) => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export class Flashcards {
|
export class Flashcards {
|
||||||
db: IDBDatabase;
|
db!: IDBDatabase;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
const req = indexedDB.open("FlashCardDB", 1);
|
const req = indexedDB.open("FlashCardDB", 1);
|
||||||
|
@ -16,6 +16,11 @@ export class Flashcards {
|
||||||
req.onsuccess = () => {
|
req.onsuccess = () => {
|
||||||
this.db = req.result;
|
this.db = req.result;
|
||||||
};
|
};
|
||||||
|
req.onerror = () => {
|
||||||
|
throw new Error(
|
||||||
|
`Error initializing the database backend, ${req.error}. This shouldn't ever happen`
|
||||||
|
);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
addFlashcard(t: Translation | Flashcard): Promise<Flashcard> {
|
addFlashcard(t: Translation | Flashcard): Promise<Flashcard> {
|
||||||
|
@ -43,14 +48,16 @@ export class Flashcards {
|
||||||
}
|
}
|
||||||
|
|
||||||
removeFlashcard(card: Flashcard): Promise<void> {
|
removeFlashcard(card: Flashcard): Promise<void> {
|
||||||
let req = this.db
|
if (card.id) {
|
||||||
.transaction(["flashcards"], "readwrite")
|
let req = this.db
|
||||||
.objectStore("flashcards")
|
.transaction(["flashcards"], "readwrite")
|
||||||
.delete(card.id);
|
.objectStore("flashcards")
|
||||||
return new Promise((resolve, reject) => {
|
.delete(card.id);
|
||||||
req.onsuccess = () => resolve();
|
return new Promise((resolve, reject) => {
|
||||||
req.onerror = () => reject(req.error);
|
req.onsuccess = () => resolve();
|
||||||
});
|
req.onerror = () => reject(req.error);
|
||||||
|
});
|
||||||
|
} else return Promise.reject("Undefined ID");
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllCards(): Promise<Array<Flashcard>> {
|
async getAllCards(): Promise<Array<Flashcard>> {
|
||||||
|
|
|
@ -22,7 +22,7 @@ declare interface Window {
|
||||||
const observer = new MutationObserver((mutations) => {
|
const observer = new MutationObserver((mutations) => {
|
||||||
console.log(mutations);
|
console.log(mutations);
|
||||||
const wasTranslating = mutations.some((m) =>
|
const wasTranslating = mutations.some((m) =>
|
||||||
m.oldValue.split(" ").some((c) => c == "translating")
|
m.oldValue!.split(" ").some((c) => c == "translating")
|
||||||
);
|
);
|
||||||
if (wasTranslating && !isTranslating()) {
|
if (wasTranslating && !isTranslating()) {
|
||||||
sendTranslation();
|
sendTranslation();
|
||||||
|
|
|
@ -46,9 +46,9 @@ export class GTranslateScraper {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
onTranslationRecieved(message: Translation) {
|
onTranslationRecieved(message: Translation) {
|
||||||
this.resolveFn(message);
|
if (this.resolveFn) this.resolveFn(message);
|
||||||
this.resolveFn = null;
|
this.resolveFn = undefined;
|
||||||
this.rejectFn = null;
|
this.rejectFn = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
translate(to_translate: string): Promise<Translation> {
|
translate(to_translate: string): Promise<Translation> {
|
||||||
|
@ -68,7 +68,7 @@ const allowIFrameAccess = (info: WebRequest.OnHeadersReceivedDetailsType) => {
|
||||||
if (info.documentUrl != document.URL) return;
|
if (info.documentUrl != document.URL) return;
|
||||||
|
|
||||||
let headers = info.responseHeaders;
|
let headers = info.responseHeaders;
|
||||||
headers = headers.filter((header) => {
|
headers = headers?.filter((header) => {
|
||||||
let h = header.name.toString().toLowerCase();
|
let h = header.name.toString().toLowerCase();
|
||||||
h != "x-frame-options" && h != "frame-options";
|
h != "x-frame-options" && h != "frame-options";
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,36 +2,41 @@
|
||||||
import { browser, Runtime } from "webextension-polyfill-ts";
|
import { browser, Runtime } from "webextension-polyfill-ts";
|
||||||
|
|
||||||
export class Communicator {
|
export class Communicator {
|
||||||
setEnabledCallback: (value: boolean, sender: Runtime.MessageSender) => void;
|
setEnabledCallback?: (value: boolean, sender: Runtime.MessageSender) => void;
|
||||||
getEnabledCallback: (sender: Runtime.MessageSender) => Promise<boolean>;
|
getEnabledCallback?: (sender: Runtime.MessageSender) => Promise<boolean>;
|
||||||
translateCallback: (
|
translateCallback?: (
|
||||||
toTranslate: string,
|
toTranslate: string,
|
||||||
sender: Runtime.MessageSender
|
sender: Runtime.MessageSender
|
||||||
) => Promise<Translation>;
|
) => Promise<Translation>;
|
||||||
|
addFlashcardCallback?: (
|
||||||
addFlashcardCallback: (
|
|
||||||
value: Translation | Flashcard,
|
value: Translation | Flashcard,
|
||||||
sender: Runtime.MessageSender
|
sender: Runtime.MessageSender
|
||||||
) => Promise<Flashcard>;
|
) => Promise<Flashcard>;
|
||||||
removeFlashcardCallback: (
|
removeFlashcardCallback?: (
|
||||||
value: Flashcard,
|
value: Flashcard,
|
||||||
sender: Runtime.MessageSender
|
sender: Runtime.MessageSender
|
||||||
) => Promise<Flashcard>;
|
) => Promise<void>;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
browser.runtime.onMessage.addListener(
|
browser.runtime.onMessage.addListener(
|
||||||
(c: command, s: Runtime.MessageSender) => {
|
(c: command, s: Runtime.MessageSender) => {
|
||||||
switch (c.commandKind) {
|
try {
|
||||||
case commandKinds.setEnabled:
|
switch (c.commandKind) {
|
||||||
return this.setEnabledCallback(c.value, s);
|
case commandKinds.setEnabled:
|
||||||
case commandKinds.getEnabled:
|
return this.setEnabledCallback!(c.value, s);
|
||||||
return this.getEnabledCallback(s);
|
case commandKinds.getEnabled:
|
||||||
case commandKinds.translate:
|
return this.getEnabledCallback!(s);
|
||||||
return this.translateCallback(c.toTranslate, s);
|
case commandKinds.translate:
|
||||||
case commandKinds.addFlashcard:
|
return this.translateCallback!(c.toTranslate, s);
|
||||||
return this.addFlashcardCallback(c.card, s);
|
case commandKinds.addFlashcard:
|
||||||
case commandKinds.removeFlashcard:
|
return this.addFlashcardCallback!(c.card, s);
|
||||||
return this.removeFlashcardCallback(c.card, s);
|
case commandKinds.removeFlashcard:
|
||||||
|
return this.removeFlashcardCallback!(c.card, s);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof ReferenceError)
|
||||||
|
console.warn(`Unimplemented command ${c.commandKind}`);
|
||||||
|
else throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -46,12 +51,10 @@ export class Communicator {
|
||||||
commandKind: commandKinds.translate,
|
commandKind: commandKinds.translate,
|
||||||
toTranslate: toTranslate,
|
toTranslate: toTranslate,
|
||||||
});
|
});
|
||||||
static addFlashcard = (card: Flashcard | Translation) => {
|
static addFlashcard = (card: Flashcard | Translation): Promise<Flashcard> =>
|
||||||
sendMessage({ commandKind: commandKinds.addFlashcard, card: card });
|
sendMessage({ commandKind: commandKinds.addFlashcard, card: card });
|
||||||
};
|
static removeFlashcard = (card: Flashcard) =>
|
||||||
static removeFlashcard = (card: Flashcard) => {
|
|
||||||
sendMessage({ commandKind: commandKinds.removeFlashcard, card: card });
|
sendMessage({ commandKind: commandKinds.removeFlashcard, card: card });
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendMessage = (m: command) => browser.runtime.sendMessage(m);
|
const sendMessage = (m: command) => browser.runtime.sendMessage(m);
|
||||||
|
|
|
@ -29,7 +29,7 @@ declare global {
|
||||||
const onSelectionChange = () => {
|
const onSelectionChange = () => {
|
||||||
tippyInstance.hide();
|
tippyInstance.hide();
|
||||||
clearTimeout(timeoutID);
|
clearTimeout(timeoutID);
|
||||||
if (document.getSelection().type == "Range")
|
if (document.getSelection()?.type == "Range")
|
||||||
timeoutID = window.setTimeout(tippyInstance.show, 500);
|
timeoutID = window.setTimeout(tippyInstance.show, 500);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -41,16 +41,16 @@ declare global {
|
||||||
trigger: "manual",
|
trigger: "manual",
|
||||||
interactive: true,
|
interactive: true,
|
||||||
getReferenceClientRect: () =>
|
getReferenceClientRect: () =>
|
||||||
document.getSelection().getRangeAt(0).getBoundingClientRect(),
|
document.getSelection()!.getRangeAt(0).getBoundingClientRect(),
|
||||||
onCreate: (instance) => {
|
onCreate: (instance) => {
|
||||||
translateElement.addEventListener("translationFinished", () =>
|
translateElement.addEventListener("translationFinished", () =>
|
||||||
instance.popperInstance.update()
|
instance.popperInstance!.update()
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onShow: () => {
|
onShow: () => {
|
||||||
translateElement.setAttribute(
|
translateElement.setAttribute(
|
||||||
"translate",
|
"translate",
|
||||||
document.getSelection().toString()
|
document.getSelection()?.toString() ?? ""
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,10 +7,12 @@ class LingoTranslate extends HTMLElement {
|
||||||
translationElm: LingoTranslation;
|
translationElm: LingoTranslation;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.attachShadow({ mode: "open" });
|
const shadow = this.attachShadow({ mode: "open" });
|
||||||
this.shadowRoot.innerHTML = `<lingo-loading></lingo-loading> <lingo-translation></lingo-translation>`;
|
shadow.innerHTML = `<lingo-loading></lingo-loading> <lingo-translation></lingo-translation>`;
|
||||||
this.loadingElm = this.shadowRoot.querySelector("lingo-loading");
|
this.loadingElm = <LingoLoading>shadow.querySelector("lingo-loading");
|
||||||
this.translationElm = this.shadowRoot.querySelector("lingo-translation");
|
this.translationElm = <LingoTranslation>(
|
||||||
|
shadow.querySelector("lingo-translation")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render = () => {
|
render = () => {
|
||||||
|
@ -25,8 +27,7 @@ class LingoTranslate extends HTMLElement {
|
||||||
this.loadingElm.hidden = true;
|
this.loadingElm.hidden = true;
|
||||||
this.translationElm.hidden = false;
|
this.translationElm.hidden = false;
|
||||||
|
|
||||||
this.translationElm.setAttribute("src", t.src);
|
this.translationElm.translation = t;
|
||||||
this.translationElm.setAttribute("translation", t.result);
|
|
||||||
this.dispatchEvent(new Event("translationFinished"));
|
this.dispatchEvent(new Event("translationFinished"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -62,44 +63,46 @@ class LingoTranslation extends HTMLElement {
|
||||||
srcElm: HTMLSpanElement;
|
srcElm: HTMLSpanElement;
|
||||||
translateElm: HTMLSpanElement;
|
translateElm: HTMLSpanElement;
|
||||||
addToCollection: HTMLButtonElement;
|
addToCollection: HTMLButtonElement;
|
||||||
|
private _translation?: Translation;
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.attachShadow({ mode: "open" });
|
const shadow = this.attachShadow({ mode: "open" });
|
||||||
|
|
||||||
let style = document.createElement("style");
|
let style = document.createElement("style");
|
||||||
style.textContent = translationCSS;
|
style.textContent = translationCSS;
|
||||||
this.shadowRoot.appendChild(style);
|
shadow.appendChild(style);
|
||||||
|
|
||||||
this.shadowRoot.innerHTML = `
|
shadow.innerHTML = `
|
||||||
<div id="translation">
|
<div id="translation">
|
||||||
<span id="src"></span> - <span id="translated"></span>
|
<span id="src"></span> - <span id="translated"></span>
|
||||||
</div>
|
</div>
|
||||||
<button is="toggleButton"> Add to collection </button>
|
<button is="toggleButton"> Add to collection </button>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
this.srcElm = this.shadowRoot.querySelector("#src");
|
this.srcElm = <HTMLSpanElement>shadow.querySelector("#src");
|
||||||
this.translateElm = this.shadowRoot.querySelector("#translated");
|
this.translateElm = <HTMLSpanElement>shadow.querySelector("#translated");
|
||||||
|
|
||||||
|
this.addToCollection = <HTMLButtonElement>shadow.querySelector("button");
|
||||||
|
|
||||||
this.addToCollection = this.shadowRoot.querySelector("button");
|
|
||||||
this.addToCollection.addEventListener("click", () =>
|
this.addToCollection.addEventListener("click", () =>
|
||||||
Communicator.addFlashcard({
|
Communicator.addFlashcard(this.translation)
|
||||||
src: this.getAttribute("src"),
|
|
||||||
result: this.getAttribute("translation"),
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render = () => {
|
public set translation(v: Translation) {
|
||||||
this.srcElm.textContent = this.getAttribute("src");
|
this._translation = v;
|
||||||
this.translateElm.textContent = this.getAttribute("translation");
|
|
||||||
};
|
|
||||||
|
|
||||||
attributeChangedCallback() {
|
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
static get observedAttributes() {
|
public get translation(): Translation {
|
||||||
return ["src", "translation"];
|
if (this._translation == null)
|
||||||
|
throw new Error("No translation object provided");
|
||||||
|
return this._translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render = () => {
|
||||||
|
this.srcElm.textContent = this.translation.src;
|
||||||
|
this.translateElm.textContent = this.translation.result;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
customElements.define("lingo-translation", LingoTranslation);
|
customElements.define("lingo-translation", LingoTranslation);
|
||||||
|
|
|
@ -5,6 +5,6 @@
|
||||||
<title></title>
|
<title></title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<button is="extension-toggle"></button>
|
<button is="lingo-toggle"></button>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import "./popup.scss";
|
||||||
|
|
||||||
const con = new Communicator();
|
const con = new Communicator();
|
||||||
|
|
||||||
class ExtensionToggle extends HTMLButtonElement {
|
class Toggle extends HTMLButtonElement {
|
||||||
isON: boolean = false;
|
isON: boolean = false;
|
||||||
textContent: string = "OFF";
|
textContent: string = "OFF";
|
||||||
|
|
||||||
|
@ -27,23 +27,21 @@ class ExtensionToggle extends HTMLButtonElement {
|
||||||
this.addEventListener("click", () => {
|
this.addEventListener("click", () => {
|
||||||
this.on = !this.on;
|
this.on = !this.on;
|
||||||
|
|
||||||
const toggleEvent = new CustomEvent("extensionToggled", {
|
const toggleEvent = new CustomEvent("toggled", {
|
||||||
detail: this.on,
|
detail: this.on,
|
||||||
});
|
});
|
||||||
this.dispatchEvent(toggleEvent);
|
this.dispatchEvent(toggleEvent);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
customElements.define("extension-toggle", ExtensionToggle, {
|
customElements.define("lingo-toggle", Toggle, {
|
||||||
extends: "button",
|
extends: "button",
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggle = <ExtensionToggle>(
|
const toggle = <Toggle>document.querySelector("button[is=extension-toggle]");
|
||||||
document.querySelector("button[is=extension-toggle]")
|
toggle.addEventListener("toggled", ((e: CustomEvent) => {
|
||||||
);
|
Communicator.setEnabled(e.detail);
|
||||||
toggle.addEventListener("extensionToggled", (e: CustomEvent) =>
|
}) as EventListener); //Hate to do this but ts forced me
|
||||||
Communicator.setEnabled(e.detail)
|
|
||||||
);
|
|
||||||
|
|
||||||
con.setEnabledCallback = (v) => (toggle.on = v);
|
con.setEnabledCallback = (v) => (toggle.on = v);
|
||||||
Communicator.getEnabled().then((v) => (toggle.on = v));
|
Communicator.getEnabled().then((v) => (toggle.on = v));
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
"target": "es6",
|
"target": "es6",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"esModuleInterop": true
|
"esModuleInterop": true,
|
||||||
|
"strict": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue