Options page

This commit is contained in:
a 2020-08-20 15:40:04 +02:00
parent 5451b3713e
commit 9ede15c7b3
11 changed files with 119 additions and 39 deletions

View File

@ -4,6 +4,8 @@
"description": "Lingo is a small browser extension to help you learn languages",
"main": "webpack.config.js",
"dependencies": {
"@sveltejs/svelte-virtual-list": "^3.0.1",
"svelte-feather-icons": "^3.2.2",
"svelte-select": "^3.11.0",
"tippy.js": "^6.2.5"
},
@ -52,6 +54,9 @@
}
},
"lint-staged": {
"*/**": ["eslint --fix ","prettier --write"]
"*/**": [
"eslint --fix ",
"prettier --write"
]
}
}

View File

@ -7,9 +7,13 @@ import content_script from "../frontend/content_script/content_script.ts?file";
const con = new BackgroundMessenger();
const scraper = new GTranslateScraper();
con.addMessageListener("translate", async (toTranslate, sender) =>
scraper.translate(toTranslate, await getCurrentLanguages(), sender!.tab?.id)
);
con.addMessageListener("translate", async (toTranslate, sender) => {
return scraper.translate(
toTranslate,
await getCurrentLanguages(),
sender!.tab?.id
);
});
con.addMessageListener("getLanguages", () => scraper.languages);

View File

@ -1,7 +1,12 @@
import { newPromise } from "../utils";
type flashcardChangedCallback = (
card: Flashcard,
change: "added" | "removed"
) => void;
export class Flashcards {
db: Promise<IDBDatabase>;
private callbacks: flashcardChangedCallback[] = [];
constructor() {
const [promise, resolve, reject] = newPromise<IDBDatabase>();
@ -28,8 +33,8 @@ export class Flashcards {
}
async addFlashcard(t: Translation | Flashcard): Promise<Flashcard> {
let card: Flashcard;
if ("dateAdded" in t && "exported" in t) card = t;
let card: Omit<Flashcard, "id"> & { id?: IDBValidKey };
if ("id" in t) card = t;
else {
card = {
...t,
@ -41,11 +46,16 @@ export class Flashcards {
const req = (await this.db)
.transaction(["flashcards"], "readwrite")
.objectStore("flashcards")
.add(card);
.put(card);
const [promise, resolve, reject] = newPromise<Flashcard>();
req.onsuccess = () => {
card.id = req.result;
resolve(card);
const newCard = {
id: req.result,
...card,
};
resolve(newCard);
this.callbacks.forEach((c) => c(newCard, "added"));
};
req.onerror = () => reject(req.error);
return promise;
@ -59,7 +69,21 @@ export class Flashcards {
.delete(card.id);
const [promise, resolve, reject] = newPromise<void>();
req.onsuccess = () => resolve();
req.onsuccess = () => {
resolve();
this.callbacks.forEach((c) => c(card, "removed"));
};
req.onerror = () => reject(req.error);
return promise;
}
async getCard(cardID: IDBValidKey): Promise<Flashcard | undefined> {
const req = (await this.db)
.transaction(["flashcards"], "readonly")
.objectStore("flashcards")
.get(cardID);
const [promise, resolve, reject] = newPromise<Flashcard | undefined>();
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
return promise;
}
@ -75,4 +99,48 @@ export class Flashcards {
req.onerror = () => reject(req.error);
return promise;
}
async getAllKeys(): Promise<IDBValidKey[]> {
const req = (await this.db)
.transaction(["flashcards"], "readonly")
.objectStore("flashcards")
.getAllKeys();
const [promise, resolve, reject] = newPromise<IDBValidKey[]>();
req.onsuccess = () => resolve(req.result);
req.onerror = () => reject(req.error);
return promise;
}
async getCardFromTransRequest(src: string, language: LanguagePair) {
const [promise, resolve, reject] = newPromise<Flashcard | undefined>();
const req = (await this.db)
.transaction(["flashcards"], "readonly")
.objectStore("flashcards")
.index("src")
.openCursor(IDBKeyRange.only(src));
req.onsuccess = () => {
const cursor = req.result;
const res = cursor?.value as Flashcard | undefined;
if (
res?.languages?.srcLang?.code == language.srcLang.code &&
res?.languages?.dstLang?.code == language.dstLang.code
)
resolve(res);
else if (cursor) cursor.continue();
else resolve(undefined);
};
req.onerror = reject;
return promise;
}
addChangeCallback(callback: flashcardChangedCallback) {
this.callbacks.push(callback);
console.log(this.callbacks);
}
removeChangeCallback(callback: flashcardChangedCallback) {
this.callbacks = this.callbacks.filter((f) => f != callback);
}
}

View File

@ -30,7 +30,7 @@ interface getLanguages extends commandFunction {
interface translate extends commandFunction {
args: string;
return: Translation;
return: Promise<Translation | Flashcard>;
}
interface getCurrentLanguages extends commandFunction {
@ -80,7 +80,7 @@ export class FrontendMessenger extends Communicator<
runCommand<K extends keyof BackgroundCommands>(
command: K,
args: BackgroundCommands[K]["args"]
): BackgroundCommands[K]["return"] {
): Promise<BackgroundCommands[K]["return"]> {
const message = this.getCommandMessage(command, args);
return browser.runtime.sendMessage(message);
}

5
src/file.d.ts vendored
View File

@ -2,3 +2,8 @@ declare module "*?file" {
const file: string;
export = file;
}
declare module "*.svg" {
const file: string;
export = file;
}

View File

@ -3,9 +3,10 @@
import type { FrontendMessenger } from "../../background_frontend_commands";
let connection = getContext("connection") as FrontendMessenger;
export let trans: Translation;
export let trans: Translation | Flashcard;
let card: Flashcard | undefined;
$: if ("id" in trans) card = trans;
const addFlashcard = async () => {
card = await connection.runCommand("addFlashcard", trans);
};
@ -26,7 +27,7 @@
card
</button>
{:else}
<button on:click={removeFlashcard} class="enabled">
<button on:click={removeFlashcard} class="remove">
Remove
<br />
card
@ -37,6 +38,7 @@
<style lang="scss">
@use "../color_scheme";
@use "../common";
.translatedContainer {
display: flex;
@ -48,23 +50,16 @@
}
button {
@include common.button;
font-size: 0.8em;
border: 0;
min-width: 9ch;
border-radius: 2px;
min-height: 100%;
cursor: pointer;
background-color: var(--green-1);
&:hover {
background-color: var(--green-2);
}
&.enabled {
background-color: var(--red-1);
&:hover {
background-color: var(--red-2);
}
@include common.button_green;
&.remove {
@include common.button_red;
}
}
</style>

View File

@ -33,7 +33,8 @@
</div>
<style lang="scss">
@use "../color_scheme.scss";
@use "../color_scheme";
@use "../common";
#container {
display: flex;
@ -50,6 +51,7 @@
display: none;
}
label {
@include common.button;
display: flex;
align-items: center;
justify-content: center;
@ -61,17 +63,9 @@
font-weight: 500;
cursor: pointer;
background-color: var(--green-1);
&:hover {
background-color: var(--green-2);
}
@include common.button_green;
&.enabled {
background-color: var(--red-1);
&:hover {
background-color: var(--red-2);
}
@include common.button_red;
}
}
</style>

View File

@ -8,7 +8,7 @@ declare global {
}
interface Flashcard {
id?: IDBValidKey;
id: IDBValidKey;
src: string;
result: string;
dateAdded: Date;

View File

@ -1,5 +1,5 @@
type resolveCallback<T> = (value: T) => void;
type rejectCallback = (reason: unknown) => void;
type rejectCallback = (reason?: unknown) => void;
export const newPromise = <T>(): [
Promise<T>,

View File

@ -54,7 +54,6 @@ let options = {
},
{
test: /\.(html|svelte)$/,
exclude: /node_modules/,
use: {
loader: "svelte-loader",
options: {

View File

@ -112,6 +112,11 @@
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
"@sveltejs/svelte-virtual-list@^3.0.1":
version "3.0.1"
resolved "https://registry.yarnpkg.com/@sveltejs/svelte-virtual-list/-/svelte-virtual-list-3.0.1.tgz#3784d6426508836b4471bba8ba293430e73717d8"
integrity sha512-aF9TptS7NKKS7/TqpsxQBSDJ9Q0XBYzBehCeIC5DzdMEgrJZpIYao9LRLnyyo6SVodpapm2B7FE/Lj+FSA5/SQ==
"@szmarczak/http-timer@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
@ -6195,6 +6200,11 @@ svelte-dev-helper@^1.1.9:
resolved "https://registry.yarnpkg.com/svelte-dev-helper/-/svelte-dev-helper-1.1.9.tgz#7d187db5c6cdbbd64d75a32f91b8998bde3273c3"
integrity sha1-fRh9tcbNu9ZNdaMvkbiZi94yc8M=
svelte-feather-icons@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/svelte-feather-icons/-/svelte-feather-icons-3.2.2.tgz#fdb4ecc7ac9127442d06d8bbeee52d3be0491834"
integrity sha512-GY86mGZYjZCRRnY2t5caiY+2gzSWrYvG8dUjhnOi6YlaWVZEAzDOBuTDiZ1abOz2mM9fCpdpbgj1JZajjzEEAw==
svelte-language-server@*:
version "0.10.90"
resolved "https://registry.yarnpkg.com/svelte-language-server/-/svelte-language-server-0.10.90.tgz#888d1371f0ea8ba2d9bf56da8f086ce0de1df60f"