Initial work on flashcards
This commit is contained in:
parent
d94cfdf01d
commit
057bc77990
7 changed files with 128 additions and 16 deletions
|
@ -1,10 +1,10 @@
|
||||||
import { browser, Runtime, Tabs } from "webextension-polyfill-ts";
|
import { browser, Runtime, Tabs } from "webextension-polyfill-ts";
|
||||||
import { GTranslateScraper } from "./gtranslate_scraper";
|
import { GTranslateScraper } from "./gtranslate_scraper";
|
||||||
|
import { Flashcards } from "./database";
|
||||||
console.log("Background script loaded");
|
|
||||||
|
|
||||||
const scraper = new GTranslateScraper();
|
const scraper = new GTranslateScraper();
|
||||||
console.log(scraper);
|
const db = new Flashcards();
|
||||||
|
console.log(db);
|
||||||
|
|
||||||
const getTab = async (s: Runtime.MessageSender): Promise<Tabs.Tab> => {
|
const getTab = async (s: Runtime.MessageSender): Promise<Tabs.Tab> => {
|
||||||
if (s.tab) return s.tab;
|
if (s.tab) return s.tab;
|
||||||
|
@ -53,6 +53,8 @@ browser.runtime.onMessage.addListener(
|
||||||
return getEnabledCommand(s);
|
return getEnabledCommand(s);
|
||||||
case commands.translate:
|
case commands.translate:
|
||||||
return scraper.translate(c.toTranslate);
|
return scraper.translate(c.toTranslate);
|
||||||
|
case commands.addFlashcard:
|
||||||
|
return db.addTranslation(c.translation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
59
src/background/database.ts
Normal file
59
src/background/database.ts
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
export interface flashcard {
|
||||||
|
id?: IDBValidKey;
|
||||||
|
src: string;
|
||||||
|
result: string;
|
||||||
|
dateAdded: Date;
|
||||||
|
exported: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Flashcards {
|
||||||
|
db: IDBDatabase;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
const req = indexedDB.open("FlashCardDB", 1);
|
||||||
|
req.onupgradeneeded = () => {
|
||||||
|
let objectStore = req.result.createObjectStore("flashcards", {
|
||||||
|
keyPath: "id",
|
||||||
|
autoIncrement: true,
|
||||||
|
});
|
||||||
|
objectStore.createIndex("src", "src", { unique: true });
|
||||||
|
objectStore.createIndex("result", "result");
|
||||||
|
objectStore.createIndex("dateAdded", "dateAdded");
|
||||||
|
objectStore.createIndex("exported", "exported");
|
||||||
|
};
|
||||||
|
req.onsuccess = () => {
|
||||||
|
this.db = req.result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
addTranslation(t: Translation): Promise<flashcard> {
|
||||||
|
let card: flashcard = {
|
||||||
|
...t,
|
||||||
|
dateAdded: new Date(),
|
||||||
|
exported: false,
|
||||||
|
};
|
||||||
|
let req = this.db
|
||||||
|
.transaction(["flashcards"], "readwrite")
|
||||||
|
.objectStore("flashcards")
|
||||||
|
.add(card);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
req.onsuccess = () => {
|
||||||
|
card.id = req.result;
|
||||||
|
resolve(card);
|
||||||
|
};
|
||||||
|
req.onerror = () => reject(req.error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllCards(): Promise<Array<flashcard>> {
|
||||||
|
let req = this.db
|
||||||
|
.transaction(["flashcards"], "readonly")
|
||||||
|
.objectStore("flashcards")
|
||||||
|
.getAll();
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
req.onsuccess = () => resolve(req.result);
|
||||||
|
req.onerror = () => reject(req.error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
import { browser } from "webextension-polyfill-ts";
|
import { browser } from "webextension-polyfill-ts";
|
||||||
import "./gtranslate_types";
|
|
||||||
declare interface Window {
|
declare interface Window {
|
||||||
hasRun: boolean;
|
hasRun: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import "./gtranslate_types";
|
|
||||||
import { browser, WebRequest, Runtime } from "webextension-polyfill-ts";
|
import { browser, WebRequest, Runtime } from "webextension-polyfill-ts";
|
||||||
|
|
||||||
export class GTranslateScraper {
|
export class GTranslateScraper {
|
||||||
iframe: HTMLIFrameElement;
|
iframe: HTMLIFrameElement;
|
||||||
conn?: Runtime.Port;
|
conn?: Runtime.Port;
|
||||||
resolveFn?: (value: TranslationResponse) => void;
|
resolveFn?: (value: Translation) => void;
|
||||||
rejectFn?: (reason: String) => void;
|
rejectFn?: (reason: String) => void;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -46,13 +45,13 @@ export class GTranslateScraper {
|
||||||
document.body.appendChild(iframe);
|
document.body.appendChild(iframe);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
onTranslationRecieved(message: TranslationResponse) {
|
onTranslationRecieved(message: Translation) {
|
||||||
this.resolveFn(message);
|
this.resolveFn(message);
|
||||||
this.resolveFn = null;
|
this.resolveFn = null;
|
||||||
this.rejectFn = null;
|
this.rejectFn = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
translate(to_translate: string): Promise<TranslationResponse> {
|
translate(to_translate: string): Promise<Translation> {
|
||||||
if (this.rejectFn) this.rejectFn("Got a different translation request");
|
if (this.rejectFn) this.rejectFn("Got a different translation request");
|
||||||
if (!this.conn) return Promise.reject("The translator is not yet ready");
|
if (!this.conn) return Promise.reject("The translator is not yet ready");
|
||||||
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
type TranslationRequest = string;
|
|
||||||
interface TranslationResponse {
|
|
||||||
src: string;
|
|
||||||
result: string;
|
|
||||||
}
|
|
|
@ -15,9 +15,14 @@ class LingoTranslate extends HTMLElement {
|
||||||
commandKind: commands.translate,
|
commandKind: commands.translate,
|
||||||
toTranslate: toTranslate,
|
toTranslate: toTranslate,
|
||||||
});
|
});
|
||||||
translation.then((t: TranslationResponse) => {
|
translation.then((t: Translation) => {
|
||||||
if (t.src == this.getAttribute("translate")) {
|
if (t.src == this.getAttribute("translate")) {
|
||||||
this.shadowRoot.textContent = t.result;
|
this.shadowRoot.innerHTML = "";
|
||||||
|
|
||||||
|
let translationElement = document.createElement("lingo-translation");
|
||||||
|
translationElement.setAttribute("src", t.src);
|
||||||
|
translationElement.setAttribute("translation", t.result);
|
||||||
|
this.shadowRoot.appendChild(translationElement);
|
||||||
this.dispatchEvent(new Event("translationFinished"));
|
this.dispatchEvent(new Event("translationFinished"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -48,3 +53,44 @@ class LingoLoading extends HTMLElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
customElements.define("lingo-loading", LingoLoading);
|
customElements.define("lingo-loading", LingoLoading);
|
||||||
|
|
||||||
|
class LingoTranslation extends HTMLElement {
|
||||||
|
srcElm: HTMLSpanElement;
|
||||||
|
translateElm: HTMLSpanElement;
|
||||||
|
addToCollection: HTMLButtonElement;
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
const shadow = this.attachShadow({ mode: "open" });
|
||||||
|
|
||||||
|
this.translateElm = document.createElement("span");
|
||||||
|
this.srcElm = document.createElement("span");
|
||||||
|
this.addToCollection = document.createElement("button");
|
||||||
|
this.addToCollection.addEventListener("click", () =>
|
||||||
|
browser.runtime.sendMessage({
|
||||||
|
commandKind: commands.addFlashcard,
|
||||||
|
translation: {
|
||||||
|
src: this.getAttribute("src"),
|
||||||
|
translation: this.getAttribute("translation"),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
shadow.appendChild(this.translateElm);
|
||||||
|
shadow.appendChild(this.srcElm);
|
||||||
|
shadow.appendChild(this.addToCollection);
|
||||||
|
}
|
||||||
|
|
||||||
|
render = () => {
|
||||||
|
this.srcElm.textContent = this.getAttribute("src");
|
||||||
|
this.translateElm.textContent = this.getAttribute("translation");
|
||||||
|
};
|
||||||
|
|
||||||
|
attributeChangedCallback() {
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
static get observedAttributes() {
|
||||||
|
return ["src", "translation"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
customElements.define("lingo-translation", LingoTranslation);
|
||||||
|
|
14
src/types.d.ts
vendored
14
src/types.d.ts
vendored
|
@ -7,6 +7,7 @@ declare const enum commands {
|
||||||
setEnabled = "setEnabled",
|
setEnabled = "setEnabled",
|
||||||
getEnabled = "getEnabled",
|
getEnabled = "getEnabled",
|
||||||
translate = "translate",
|
translate = "translate",
|
||||||
|
addFlashcard = "addFlashcard",
|
||||||
}
|
}
|
||||||
interface setEnabled {
|
interface setEnabled {
|
||||||
commandKind: commands.setEnabled;
|
commandKind: commands.setEnabled;
|
||||||
|
@ -22,4 +23,15 @@ interface translate {
|
||||||
toTranslate: string;
|
toTranslate: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
type command = setEnabled | getEnabled | translate;
|
interface addFlashcard {
|
||||||
|
commandKind: commands.addFlashcard;
|
||||||
|
translation: Translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
type command = setEnabled | getEnabled | translate | addFlashcard;
|
||||||
|
|
||||||
|
type TranslationRequest = string;
|
||||||
|
interface Translation {
|
||||||
|
src: string;
|
||||||
|
result: string;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue