From e885ea2976fafaab73aed6cb669b6b5092e2a603 Mon Sep 17 00:00:00 2001
From: Aiden Gardner <19619206+aiden2480@users.noreply.github.com>
Date: Fri, 5 Apr 2024 20:03:52 +1100
Subject: [PATCH 01/10] console.image
---
js/utilities.js | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/js/utilities.js b/js/utilities.js
index 9d15775..ac41ad9 100644
--- a/js/utilities.js
+++ b/js/utilities.js
@@ -247,3 +247,27 @@ export async function fetchRandomSet() {
export async function fetchAllSets() {
return (await chrome.storage.local.get("customsets")).customsets;
}
+
+/**
+ * Prints an image to the console
+ *
+ * @param {URL} url The URL of the image to print to the console
+ */
+console.image = function(url) {
+ var img = new Image();
+
+ img.onload = function() {
+ var properties = [
+ `font-size: 1px`,
+ `padding: 0px ${Math.floor(this.width / 2)}px`,
+ `line-height: ${this.height}px`,
+ `background: url(${url})`,
+ `background-size: ${this.width}px ${this.height}px`,
+ `color: transparent`,
+ ];
+
+ console.log("%c.", properties.join(";"));
+ };
+
+ img.src = url;
+};
From d3ce5ce24c981ab506ecc8c8dd4e117875c63412 Mon Sep 17 00:00:00 2001
From: Aiden Gardner <19619206+aiden2480@users.noreply.github.com>
Date: Fri, 5 Apr 2024 23:26:28 +1100
Subject: [PATCH 02/10] refactor utilities.js
---
js/utilities.js | 33 +++++++++++++++++++--------------
1 file changed, 19 insertions(+), 14 deletions(-)
diff --git a/js/utilities.js b/js/utilities.js
index ac41ad9..4f8dc8e 100644
--- a/js/utilities.js
+++ b/js/utilities.js
@@ -86,7 +86,8 @@ function convertCanvasToBlackAndWhite(canvas) {
var fabcan = document.createElement("canvas");
var fabctx = fabcan.getContext("2d");
- [fabcan.width, fabcan.height] = [248, 248];
+ fabcan.width = 248;
+ fabcan.height = 248;
for (var y=0; y < pixels.height; y++) {
for (var x=0; x < pixels.width; x++) {
@@ -129,7 +130,8 @@ export async function checkRembrandt() {
var blankctx = blankcanv.getContext("2d");
// Draw 248x248 white on a canvas
- [blankcanv.width, blankcanv.height] = [248, 248];
+ blankcanv.width = 248;
+ blankcanv.height = 248;
blankctx.fillStyle = "white";
blankctx.fillRect(0, 0, 248, 248);
@@ -172,7 +174,7 @@ export async function fetchKanjiDetails(kanji) {
const rapidAPI = atob("bjZ2SVQ5ZDU0Wm1zaEVlSlk1ZUdBSFpNQmt0cXAxV1V1Tmdqc253OWxpYXVRRVVFVXU");
const infosection = document.getElementById("infosection");
const options = {
- headers: {"x-rapidapi-key": rapidAPI},
+ headers: { "x-rapidapi-key": rapidAPI },
cache: "force-cache",
};
@@ -204,8 +206,9 @@ export async function fetchKanjiDetails(kanji) {
*/
export async function fetchSetFromID(id) {
// Finds a set from a given ID
- var sets = (await chrome.storage.local.get("customsets")).customsets;
- return sets.find(x => x.id == id);
+ var { customsets } = await chrome.storage.local.get("customsets");
+
+ return customsets.find(x => x.id == id);
}
/**
@@ -215,17 +218,17 @@ export async function fetchSetFromID(id) {
* @returns {CustomSet} Any currently enabled set
*/
export async function fetchAnySet() {
- var sets = (await chrome.storage.local.get("customsets")).customsets;
- var pass = sets.find(item => item.enabled);
+ var { customsets } = await chrome.storage.local.get("customsets");
+ var pass = customsets.find(item => item.enabled);
- // Return if found
+ // Return if any are already enabled
if (pass) return pass;
// If none are found, we enable the first set and return that one
- sets[0].enabled = true;
- await chrome.storage.local.set({ customsets: sets });
+ customsets[0].enabled = true;
+ await chrome.storage.local.set({ customsets });
- return sets[0];
+ return customsets[0];
}
/**
@@ -235,8 +238,9 @@ export async function fetchAnySet() {
*/
export async function fetchRandomSet() {
// Fetch a random set
- var sets = (await chrome.storage.local.get("customsets")).customsets;
- return sets[Math.floor(Math.random() * sets.length)];
+ var { customsets } = await chrome.storage.local.get("customsets");
+
+ return customsets[Math.floor(Math.random() * customsets.length)];
}
/**
@@ -249,7 +253,8 @@ export async function fetchAllSets() {
}
/**
- * Prints an image to the console
+ * Prints an image to the console. Credit to @adriancooney
+ * https://github.com/adriancooney/console.image
*
* @param {URL} url The URL of the image to print to the console
*/
From 1e27016a07ad04936ca1ac591f8f96a0ce9fd3b7 Mon Sep 17 00:00:00 2001
From: Aiden Gardner <19619206+aiden2480@users.noreply.github.com>
Date: Sat, 6 Apr 2024 11:51:43 +1100
Subject: [PATCH 03/10] Fix badness in background.js
---
background.js | 49 ++++++++++++++++++++++++++++++++++---------------
1 file changed, 34 insertions(+), 15 deletions(-)
diff --git a/background.js b/background.js
index 482208f..816f8ea 100644
--- a/background.js
+++ b/background.js
@@ -71,9 +71,10 @@ chrome.runtime.onInstalled.addListener(async reason => {
await chrome.storage.local.set({ selectedkanji: 0 });
}
- if ((await chrome.management.getSelf()).installType !== "development")
- chrome.runtime.setUninstallURL("https://kanjithing-backend.chocolatejade42.repl.co/uninstall");
-
+ if (!await isDevelopment()) {
+ chrome.runtime.setUninstallURL("https://www.youtube.com/watch?v=dQw4w9WgXcQ");
+ }
+
// Register context menus
chrome.contextMenus.removeAll(() => {
generateContextMenus();
@@ -92,7 +93,9 @@ chrome.runtime.onStartup.addListener(async () => {
chrome.storage.onChanged.addListener(async (changes, namespace) => {
// Console log when storage values change
- if ((await chrome.management.getSelf()).installType !== "development") return;
+ if (!await isDevelopment()) {
+ return;
+ }
for (let [key, { oldValue, newValue }] of Object.entries(changes)) {
console.debug(`${key} : ${oldValue} -> ${newValue}`);
@@ -114,7 +117,7 @@ async function ensureCorrectKanjiIcon() {
* Ensures the "Beta" badge is displayed if necessary
*/
async function ensureBetaBadge() {
- if ((await chrome.management.getSelf()).installType === "development") {
+ if (await isDevelopment()) {
chrome.action.setBadgeText({ text: "B" });
chrome.action.setBadgeBackgroundColor({ color: "#304db6" });
}
@@ -126,12 +129,18 @@ async function ensureBetaBadge() {
*/
async function ensureDefaultConfiguration() {
// Create default sets
- var sets = (await chrome.storage.local.get("customsets")).customsets;
- (sets === undefined) && await createKanjiSets();
+ var { customsets } = await chrome.storage.local.get("customsets");
+
+ if (customsets === undefined) {
+ await createKanjiSets();
+ }
// Create default settings
var { config } = await chrome.storage.local.get("config");
- (config === undefined) && await createDefaultConfig();
+
+ if (config === undefined) {
+ await createDefaultConfig();
+ }
}
/**
@@ -238,21 +247,21 @@ chrome.contextMenus.onClicked.addListener(async (info, tab) => {
// Show a little x for a second if an error occured
if (!match) return await displayBadge(tab, "X", "#D9381E", 3000);
- var sets = (await chrome.storage.local.get("customsets")).customsets;
+ var { customsets } = await chrome.storage.local.get("customsets");
if (info.menuItemId === "createnewset") {
- sets.push({
- id: sets.slice(-1)[0].id + 1,
+ customsets.push({
+ id: customsets.slice(-1)[0].id + 1,
name: "Unnamed set",
kanji: match,
enabled: true
});
- await chrome.storage.local.set({ customsets: sets });
+ await chrome.storage.local.set({ customsets });
await displayBadge(tab, "✓", "#32CD32", 3000);
if (isPopup) await chrome.storage.local.set({
- selectedunit: sets.at(-1).id,
+ selectedunit: customsets.at(-1).id,
selectedkanji: 0,
});
}
@@ -260,10 +269,10 @@ chrome.contextMenus.onClicked.addListener(async (info, tab) => {
if (info.menuItemId.startsWith("addtoset")) {
var setid = info.menuItemId.match(/addtoset(.+)/)[1];
- var set = sets.find(x => x.id == setid);
+ var set = customsets.find(x => x.id == setid);
set.kanji += match;
- await chrome.storage.local.set({ customsets: sets });
+ await chrome.storage.local.set({ customsets });
await displayBadge(tab, "✓", "#32CD32", 3000);
if (isPopup) await chrome.storage.local.set({
@@ -303,3 +312,13 @@ async function displayBadge(tab, text, colour, milliseconds) {
await chrome.action.setBadgeText({ text: current.text });
}, milliseconds);
}
+
+/**
+ *
+ * @returns A boolean indicating if the current installation context is dev
+ */
+async function isDevelopment() {
+ var { installType } = await chrome.management.getSelf();
+
+ return installType === "development";
+}
From f840aaac11bcf86883e50a8c6e6b058c354e5c1e Mon Sep 17 00:00:00 2001
From: Aiden Gardner <19619206+aiden2480@users.noreply.github.com>
Date: Sat, 6 Apr 2024 11:54:10 +1100
Subject: [PATCH 04/10] Remove bypass parameter
---
background.js | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/background.js b/background.js
index 816f8ea..b58ef08 100644
--- a/background.js
+++ b/background.js
@@ -1,5 +1,4 @@
-/* Save the current kanji */
-var current;
+/* Default sets for the initial installation */
var defaultsets = [
{"Unit one": "学校名前父母生高姉妹兄弟住所色"},
{"Unit two": "好同手紙英語何年私友行毎教場"},
@@ -110,7 +109,7 @@ async function ensureCorrectKanjiIcon() {
var { customsets, selectedset, selectedkanji } = await chrome.storage.local.get();
if ([ customsets, selectedset, selectedkanji ].includes(undefined)) return;
- setBrowserIcon(customsets[selectedset].kanji[selectedkanji], bypass=true);
+ setBrowserIcon(customsets[selectedset].kanji[selectedkanji]);
}
/**
@@ -147,12 +146,9 @@ async function ensureDefaultConfiguration() {
* Sets the browser icon to the currently selected character
*
* @param {Char} kanji The character to set the browser icon to
- * @param {Boolean} bypass Bypass same-kanji check
*/
-function setBrowserIcon(kanji, bypass=false) {
+function setBrowserIcon(kanji) {
// https://jsfiddle.net/1u37ovj9/
- if (current === kanji && !bypass) return;
-
var canvas = new OffscreenCanvas(64, 64);
var context = canvas.getContext("2d");
@@ -166,7 +162,6 @@ function setBrowserIcon(kanji, bypass=false) {
context.fillStyle = "#FFFAFA";
context.fillText(kanji, 0.5 * canvas.width, 0.825 * canvas.height);
- current = kanji;
var imageData = context.getImageData(0, 0, 64, 64);
chrome.action.setIcon({ imageData }, () => console.log(`Set browser icon to %c${kanji}`, "color: #7289da"));
}
From 2dd7d58db535fa8bf2a037d01611c5a60a586b18 Mon Sep 17 00:00:00 2001
From: Aiden Gardner <19619206+aiden2480@users.noreply.github.com>
Date: Sat, 6 Apr 2024 12:19:10 +1100
Subject: [PATCH 05/10] Remove getLastFrameOfVideo and contentURLToDataURL
---
js/utilities.js | 68 +++++--------------------------------------------
1 file changed, 7 insertions(+), 61 deletions(-)
diff --git a/js/utilities.js b/js/utilities.js
index 4f8dc8e..f10bb4e 100644
--- a/js/utilities.js
+++ b/js/utilities.js
@@ -1,77 +1,23 @@
/**
- * Takes in a video URL and gets the last frame from that video.
- * Used to compare video to canvas drawing via Rembrandt.
- *
- * @param {URL} url The URL (data or otherwise) of a video resource
- * @returns {DataURL} The last frame of that video as a data URL
- */
-function getLastFrameOfVideo(url) {
- return new Promise(async (resolve, reject) => {
- var video = document.createElement("video");
- var fabcan = document.createElement("canvas");
- var fabctx = fabcan.getContext("2d");
-
- video.addEventListener("error", reject);
- video.addEventListener("loadedmetadata", () => {
- fabcan.width = video.videoWidth;
- fabcan.height = video.videoHeight;
-
- video.addEventListener("seeked", () => {
- fabctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
-
- resolve(fabcan.toDataURL());
- });
-
- video.currentTime = video.duration;
- });
-
- video.src = await contentURLToDataURL(url);
- video.load();
- });
-}
-
-/**
- * Resizes an SVG from its original size to 248x248
+ * Resizes an square SVG and returns the new data URL
*
* @param {DataURL} dataURL The data URL of the SVG
- * @returns {DataURL} The resized element
+ * @returns {Canvas} The resized element on a canvas
*/
-function resizeSVG(dataURL) {
+function resizeSquareSVGToCanvas(dataURL, sideLength) {
return new Promise((resolve, reject) => {
var fabcan = document.createElement("canvas");
var fabctx = fabcan.getContext("2d");
var img = new Image();
img.addEventListener("load", () => {
- fabctx.drawImage(img, 0, 0, 248, 248);
- resolve(fabcan.toDataURL());
+ fabctx.drawImage(img, 0, 0, sideLength, sideLength);
+ resolve(fabcan);
})
+ fabcan.width = sideLength;
+ fabcan.height = sideLength;
img.src = dataURL;
- fabcan.width = 248;
- fabcan.height = 248;
- });
-}
-
-/**
- * Takes a content URL and fully downloads the content,
- * before converting it back to a data URL
- *
- * @param {URL} url The URL of a resource on the internet
- * @returns {DataURL} The downloaded resource
- */
-function contentURLToDataURL(url) {
- return new Promise(async (resolve, reject) => {
- var resp = await fetch(url, {cache: "force-cache"});
- var reader = new FileReader();
-
- reader.addEventListener("load", () => {
- // console.debug(reader.result);
- resolve(reader.result);
- });
-
- reader.addEventListener("error", reject);
- reader.readAsDataURL(await resp.blob());
});
}
From df20b9b6e25ba533f0ddd92e7c4d3353acd9adff Mon Sep 17 00:00:00 2001
From: Aiden Gardner <19619206+aiden2480@users.noreply.github.com>
Date: Sat, 6 Apr 2024 12:20:04 +1100
Subject: [PATCH 06/10] fetchUrlViaCorsProxy and newBlankCanvas
---
js/utilities.js | 37 ++++++++++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/js/utilities.js b/js/utilities.js
index f10bb4e..db69112 100644
--- a/js/utilities.js
+++ b/js/utilities.js
@@ -24,8 +24,8 @@ function resizeSquareSVGToCanvas(dataURL, sideLength) {
/**
* Converts a canvas to black and white for better comparison
*
- * @param {HTMLCanvas} canvas The canvas element to process
- * @returns {HTMLCanvas} The monochrome canvas
+ * @param {Canvas} canvas The canvas element to process
+ * @returns {Canvas} The monochrome canvas
*/
function convertCanvasToBlackAndWhite(canvas) {
var pixels = canvas.getContext("2d").getImageData(0, 0, 248, 248);
@@ -49,7 +49,38 @@ function convertCanvasToBlackAndWhite(canvas) {
}
fabctx.putImageData(pixels, 0, 0, 0, 0, pixels.width, pixels.height);
- return fabcan.toDataURL("image/png")
+ return fabcan;
+}
+
+/**
+ * Because cors is one of the dumbest things humans have ever invented
+ *
+ * @param {URL} url The url to request via cors proxy
+ * @returns The url page contents
+ */
+async function fetchUrlViaCorsProxy(url) {
+ var resp = await fetch(`https://api.allorigins.win/get?url=${encodeURIComponent(url)}`);
+ var json = await resp.json();
+
+ return json.contents;
+}
+
+/**
+ * Creates a new blank canvas of dimensons widthxheight
+ *
+ * @param {Integer} width The width of the canvas
+ * @param {Integer} height The height of the canvas
+ */
+function newBlankCanvas(width, height) {
+ var canvas = document.createElement("canvas");
+ var ctx = canvas.getContext("2d");
+
+ canvas.width = width;
+ canvas.height = height;
+ ctx.fillStyle = "white";
+ ctx.fillRect(0, 0, width, height);
+
+ return canvas;
}
/**
From f99cb597617341f782ca18384a38a7f1ff95695b Mon Sep 17 00:00:00 2001
From: Aiden Gardner <19619206+aiden2480@users.noreply.github.com>
Date: Sat, 6 Apr 2024 12:21:01 +1100
Subject: [PATCH 07/10] New rembrandt logic with maxOffset and cors proxy
---
js/utilities.js | 51 +++++++++++++++++--------------------------------
1 file changed, 18 insertions(+), 33 deletions(-)
diff --git a/js/utilities.js b/js/utilities.js
index db69112..123898f 100644
--- a/js/utilities.js
+++ b/js/utilities.js
@@ -88,54 +88,39 @@ function newBlankCanvas(width, height) {
* compares them to evaluate the user's drawing. This process factors
* in the complexity of the character when grading.
*
- * @returns {Float} The user's score as a percentage between 0 and 1
+ * @returns {Float} The user's score between 0 and 100
*/
export async function checkRembrandt() {
var kanji = selectedkanji.selectedOptions[0].innerText;
- // Replit backend method
- var kanjiID = (await fetchKanjiDetails(kanji)).kanji.video.mp4.split("/").at(-1);
- var comparison = await getLastFrameOfVideo("https://kanjithing-backend.chocolatejade42.repl.co/video/" + kanjiID);
-
- // SVG data URL method (broken)
- // var kanjisvg = (await fetchKanjiDetails(kanji)).kanji.video.poster;
- // var kanjisvgid = kanjisvg.split("/").at(-1);
- // var svgBase64 = await contentURLToDataURL("https://kanjithing-backend.chocolatejade42.repl.co/svg/" + kanjisvgid);
- // var comparison = await resizeSVG(svgBase64);
-
- var blankcanv = document.createElement("canvas");
- var blankctx = blankcanv.getContext("2d");
-
- // Draw 248x248 white on a canvas
- blankcanv.width = 248;
- blankcanv.height = 248;
- blankctx.fillStyle = "white";
- blankctx.fillRect(0, 0, 248, 248);
-
+ var kanjiDetails = await fetchKanjiDetails(kanji);
+ var posterUrl = kanjiDetails.kanji.video.poster;
+ var posterDataUrl = await fetchUrlViaCorsProxy(posterUrl);
+ var resizedPosterCanvas = await resizeSquareSVGToCanvas(posterDataUrl, 248);
+ var posterDataUrl = convertCanvasToBlackAndWhite(resizedPosterCanvas).toDataURL();
+
// Compare drawing with video, and blank with video
var checkrem = new Rembrandt({
- imageA: comparison,
- imageB: convertCanvasToBlackAndWhite(canvas),
- thresholdType: Rembrandt.THRESHOLD_PERCENT,
- maxThreshold: 0.2,
- maxDelta: 20,
- maxOffset: 0,
- // renderComposition: true,
- // compositionMaskColor: new Rembrandt.Color(0.54, 0.57, 0.62)
+ imageA: posterDataUrl,
+ imageB: convertCanvasToBlackAndWhite(canvas).toDataURL(),
+ maxOffset: 2,
+ renderComposition: true,
});
var blankrem = new Rembrandt({
- imageA: comparison,
- imageB: blankcanv.toDataURL(),
- // renderComposition: true,
- // compositionMaskColor: new Rembrandt.Color(0.54, 0.57, 0.62)
+ imageA: posterDataUrl,
+ imageB: newBlankCanvas(248, 248).toDataURL(),
+ maxOffset: 2,
});
var blank = await blankrem.compare();
var check = await checkrem.compare();
+ console.image(check.compositionImage.src);
// Find the drawing score relative to the complexity of the kanji
- return Math.max(1 - check.percentageDifference / blank.percentageDifference, 0) * 100;
+ var score = (1 - check.percentageDifference / blank.percentageDifference - blank.percentageDifference);
+
+ return Math.max(score, 0) * 100;
}
/**
From b66a311d4b935de36a8801927e64e68e07d6d222 Mon Sep 17 00:00:00 2001
From: Aiden Gardner <19619206+aiden2480@users.noreply.github.com>
Date: Sat, 6 Apr 2024 12:40:18 +1100
Subject: [PATCH 08/10] Update readme
---
README.md | 61 +++++++++++--------------------------------------------
1 file changed, 12 insertions(+), 49 deletions(-)
diff --git a/README.md b/README.md
index 68a8b60..5c56c94 100644
--- a/README.md
+++ b/README.md
@@ -4,19 +4,19 @@
-
+
## :shrug: A google chrome extension for practising kanji
-You can practise drawing kanji featured in the Wakatta units. That's pretty much it right now.
+You can practise drawing kanji featured in the Wakatta units. It also has other useful information like character readings and example words.
> [Install on the google chrome webstore](https://chrome.google.com/webstore/detail/kanjithing/nccfelhkfpbnefflolffkclhenplhiab)
## :gear: Installation
> The extension is available in the [google chrome store](https://chrome.google.com/webstore/detail/nccfelhkfpbnefflolffkclhenplhiab), though it can be installed from source with the following instructions
-1. [Download the repository as a zip](https://github.com/aiden2480/kanjithing/zipball/main) and extract
+1. `git clone https://github.com/aiden2480/kanjithing`
2. Navigate to [`chrome://extensions`](chrome://extensions)
3. Ensure that the `Developer mode` switch is enabled in the top right of your screen
4. Click `Load unpacked` in the top left corner of the screen
@@ -24,47 +24,18 @@ You can practise drawing kanji featured in the Wakatta units. That's pretty much
## :recycle: Update
Google chrome will automatically update the extension as I publish new updates if you install from the chrome store.
-If installing from this repository, `git clone` this repository and then run `git pull origin master` yourself.
-You'll need to go back into the [chrome extension settings](chrome://extensions) and press the refresh icon next to the extension to reload.
+If installing from this repository, run `git pull origin main`, then go back to `chrome://extensions` and press the refresh icon next to the extension to reload.
I'm using a [custom GitHub action](.github/workflows/updatewebstore.yml) to automatically publish new versions of the extension to the chrome store every time I change the `version` parameter in the `manifest.json` file.
-## :file_cabinet: API
-The kanji drawing guide videos are sourced from [KanjiAlive](https://app.kanjialive.com/api/docs), and cached using a [middleman I created](https://replit.com/@chocolatejade42/kanjithing-backend) (as RapidAPI limits requests).
-It also collates some data about the kanji which is used in the extension, such as readings, and example words.
-Requests can be made at the `/kanji/:kanji` endpoint, like so.
-
-```bash
-$ curl -L http://kanjithing-backend.chocolatejade42.repl.co/kanji/車
-```
-```json
-{
- "status": 200,
- "kanji": "車",
- "kstroke": 7,
- "kmeaning": "vehicle, wheel, car",
- "kgrade": 1,
- "kunyomi_ja": "くるま",
- "onyomi_ja": "シャ",
- "video": "https://media.kanjialive.com/kanji_animations/kanji_mp4/kuruma_00.mp4",
- "examples": [
- ["車(くるま)", "car"],
- ["電車(でんしゃ)", "train"],
- ["自転車(じてんしゃ)", "bicycle"],
- ["自動車(じどうしゃ)", "automobile"],
- ["車いす(くるまいす)", "wheel chair"],
- ["駐車する(ちゅうしゃする)", "park a car"],
- ["停車する(ていしゃする)", "stop a car or train"]
- ]
-}
-```
+## :camera_flash: Program screenshots
+
+
+
## :memo: Future features
- [ ] Able to star/favourite kanji to add them quickly to a custom set.
- [ ] Make the user guess readings of kanji in words
-- [ ] Help page
- - How to use the extention, info about tooltips, etc
- - Open on the first install
- [ ] Flashcard thing where you get the meaning of the kanji and sample words and have to draw it
- [ ] Custom flashcards to remember kanji/words
- Import from quizlet
@@ -77,20 +48,12 @@ $ curl -L http://kanjithing-backend.chocolatejade42.repl.co/kanji/車
- [ ] Right click to remove drawing (all connected strokes)
- [ ] Add tooltip banner when extension updates
- Potentially as a small subtext badge?
-- [x] Keybinds to navigate the application via keyboard
- - Up/down arrow to navigate between kanji sets
- - Left/right arrow to navigate between kanji in the currently selected set
- - R to select a random kanji in the currently selected set
- - Enter to grade kanji drawing
- - Space to play/pause/replay video guide
- - Backspace to clear drawing
- - S to star/unstar selected kanji
- - Keybinds visible in tooltips
- [ ] Use static assets for the emojis to keep design consistent between operating systems
- [ ] Event listener on the popup script to determine when the set storage has changed
- [ ] Use data from the KanjiAlive API to do pronuncation/sounds
-- [ ] Make CSS for buttons/inputs be consistent throughout the popup/settings/index pages
+- [x] Make CSS for buttons/inputs be consistent throughout the popup/settings/index pages
- [ ] Fix overlap interaction with especially long word descriptions (同 kanji)
- [x] Use a RapidAPI key in the application to fetch data (Replit downtime)
-- [ ] Unspaghettify everything
-- [ ] Add method of actually accessing the tips page
+- [ ] Display notice if character data not available
+- [ ] https://github.com/gildas-lormeau/zip.js/tree/master/dist
+- [ ] https://github.com/kanjialive/kanji-data-media/blob/master/kanji-animations/animations-mp4.zip
From 411dd2df3623ed40d64d61457f45f55156438f34 Mon Sep 17 00:00:00 2001
From: Aiden Gardner <19619206+aiden2480@users.noreply.github.com>
Date: Sat, 6 Apr 2024 12:40:39 +1100
Subject: [PATCH 09/10] fix onMessage in background
---
background.js | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/background.js b/background.js
index b58ef08..056affd 100644
--- a/background.js
+++ b/background.js
@@ -50,14 +50,13 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {(async
case "resetKanjiSets":
await chrome.storage.local.remove("customsets");
await createKanjiSets();
- sendResponse();
break;
case "ensureDefaultConfig":
await ensureDefaultConfiguration();
- sendResponse();
break;
}
+ sendResponse();
})(); return true});
/* Set up a listener for when the extension is installed/chrome restarts */
From 0dcd39f3d5f68838970d553dd3fe33e68d4ffd09 Mon Sep 17 00:00:00 2001
From: Aiden Gardner <19619206+aiden2480@users.noreply.github.com>
Date: Sat, 6 Apr 2024 12:45:22 +1100
Subject: [PATCH 10/10] Bump manifest version
---
css/popup.css | 1 +
manifest.json | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/css/popup.css b/css/popup.css
index 6fe98a8..c69c5b3 100644
--- a/css/popup.css
+++ b/css/popup.css
@@ -48,6 +48,7 @@ div#panel * {
background-color: #36393e;
color: #7289da;
border: 2px solid #7289da;
+ cursor: pointer;
}
#panel > select { height: 23px; }
diff --git a/manifest.json b/manifest.json
index 6e6fe9d..3a36baa 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
{
"name": "KanjiThing",
"description": "Learn kanji stroke order from the browser",
- "version": "2.1.1",
+ "version": "2.2.0",
"manifest_version": 3,
"permissions": ["storage", "contextMenus"],
"options_page": "settings.html",