Options page
This commit is contained in:
parent
5451b3713e
commit
9ede15c7b3
11 changed files with 119 additions and 39 deletions
|
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
5
src/file.d.ts
vendored
|
@ -2,3 +2,8 @@ declare module "*?file" {
|
|||
const file: string;
|
||||
export = file;
|
||||
}
|
||||
|
||||
declare module "*.svg" {
|
||||
const file: string;
|
||||
export = 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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -8,7 +8,7 @@ declare global {
|
|||
}
|
||||
|
||||
interface Flashcard {
|
||||
id?: IDBValidKey;
|
||||
id: IDBValidKey;
|
||||
src: string;
|
||||
result: string;
|
||||
dateAdded: Date;
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -54,7 +54,6 @@ let options = {
|
|||
},
|
||||
{
|
||||
test: /\.(html|svelte)$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: "svelte-loader",
|
||||
options: {
|
||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue