Merge pull request #3 from Lauchmelder23/v0.6.1

V0.6.1
This commit is contained in:
Lauchmelder 2022-03-21 14:08:22 +01:00 committed by GitHub
commit d7bbe06161
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 83 additions and 37 deletions

5
VERSIONS.md Normal file
View file

@ -0,0 +1,5 @@
# v0.6
## v0.6.1
* Replaced internal arrays with sets to prevent accidentally doubly caching values
* Perform startup initialization for switches (should now default to ON)
* Fixed error appearing right after installing extension

View file

@ -1,7 +1,7 @@
{ {
"name": "FuriKani", "name": "FuriKani",
"description": "Removes furigana on websites based on your WaniKani level", "description": "Removes furigana on websites based on your WaniKani level",
"version": "0.6", "version": "0.6.1",
"icons": { "icons": {
"16": "res/icon16.png", "16": "res/icon16.png",
"48": "res/icon48.png", "48": "res/icon48.png",

View file

@ -6,7 +6,7 @@
<body> <body>
<header> <header>
<h1>FuriKani</h1> <h1>FuriKani</h1>
<h2>v0.6</h2> <h2>v0.6.1</h2>
</header> </header>
<div id="token-area"> <div id="token-area">

View file

@ -1,8 +1,22 @@
chrome.storage.local.get("token", (data) => {
if(data.token !== undefined)
return
chrome.storage.local.set({
"enabled": true,
"enabledVocab": true,
"enabledKanji": true
})
})
// Query a WaniKani API endpoint with the given token
const query = (token, url) => const query = (token, url) =>
new Promise(async (resolve, reject) => { new Promise(async (resolve, reject) => {
// Create header with the authorization token
const requestHeaders = new Headers() const requestHeaders = new Headers()
requestHeaders.append("Authorization", "Bearer " + token) requestHeaders.append("Authorization", "Bearer " + token)
// Construct request
const endpoint = new Request( const endpoint = new Request(
url, url,
{ {
@ -11,6 +25,8 @@ const query = (token, url) =>
} }
) )
// Fetch the response. If it returns HTTP 200, resolve the promise,
// otherwise reject it
var result = await fetch(endpoint) var result = await fetch(endpoint)
if(!result.ok) if(!result.ok)
{ {
@ -21,6 +37,7 @@ const query = (token, url) =>
return resolve(result.json()) return resolve(result.json())
}) })
// Update the local cache with new data
const updateCache = async (token, oldLevel, newLevel) => { const updateCache = async (token, oldLevel, newLevel) => {
// If oldLevel is undefined, then a sync has never been performed (first time user) // If oldLevel is undefined, then a sync has never been performed (first time user)
if(oldLevel === undefined) if(oldLevel === undefined)
@ -39,9 +56,24 @@ const updateCache = async (token, oldLevel, newLevel) => {
// Turn the array of levels into a comma separated list // Turn the array of levels into a comma separated list
var levelURLString = levelArray.join(",") var levelURLString = levelArray.join(",")
// API endpoint + response data buffers // Data buffers
var vocabulary = new Set();
var kanji = new Set();
// If the old level is less than the new level add the old data to the new data
if(oldLevel < newLevel)
{
await chrome.storage.local.get(["vocabulary", "kanji"], (data) => {
if(data.vocabulary !== undefined && data.kanji !== undefined)
{
data.vocabulary.forEach(vocabulary.add, vocabulary)
data.kanji.forEach(kanji.add, kanji)
}
})
}
// API endpoint
var url = "https://api.wanikani.com/v2/subjects?types=vocabulary&levels=" + levelURLString var url = "https://api.wanikani.com/v2/subjects?types=vocabulary&levels=" + levelURLString
var vocabulary = []
// WaniKani only sends 1000 elements in one response and then provides us with a link to the // WaniKani only sends 1000 elements in one response and then provides us with a link to the
// next "page" of the data. We need to loop until the next page is null // next "page" of the data. We need to loop until the next page is null
@ -53,14 +85,14 @@ const updateCache = async (token, oldLevel, newLevel) => {
break break
for(let i in response.data) for(let i in response.data)
vocabulary.push(response.data[i].data.characters) vocabulary.add(response.data[i].data.characters)
url = response.pages.next_url url = response.pages.next_url
} while(url !== null) } while(url !== null)
// Extract Kanji as well // Extract Kanji as well
var url = "https://api.wanikani.com/v2/subjects?types=kanji&levels=" + levelURLString var url = "https://api.wanikani.com/v2/subjects?types=kanji&levels=" + levelURLString
var kanji = [] var kanji = new Set()
do do
{ {
@ -69,24 +101,15 @@ const updateCache = async (token, oldLevel, newLevel) => {
break break
for(let i in response.data) for(let i in response.data)
kanji.push(response.data[i].data.characters) kanji.add(response.data[i].data.characters)
url = response.pages.next_url url = response.pages.next_url
} while(url !== null) } while(url !== null)
// If the old level is less than the new level add the old data to the new data
if(oldLevel < newLevel)
{
await chrome.storage.local.get(["vocabulary", "kanji"], (data) => {
vocabulary.concat(data.vocabulary)
kanji.concat(data.kanji)
})
}
// Cache the data // Cache the data
chrome.storage.local.set({ chrome.storage.local.set({
"vocabulary": vocabulary, "vocabulary": [...vocabulary],
"kanji": kanji, "kanji": [...kanji],
"level": newLevel "level": newLevel
}) })
} }
@ -142,4 +165,4 @@ chrome.runtime.onMessage.addListener((data, sender, sendResponse) => {
}) })
// At browser start, sync with wanikani // At browser start, sync with wanikani
sync().then(value => console.log(value)).catch(reason => console.error(reason)) sync().then(value => console.log(value)).catch(reason => {})

View file

@ -1,15 +1,18 @@
// Vocab Furigana CSS
var vocabStyle = ` var vocabStyle = `
.furikani-vocabulary { .furikani-vocabulary {
display: none; display: none;
} }
` `
// Kanji Furigana CSS
var kanjiStyle = ` var kanjiStyle = `
.furikani-kanji { .furikani-kanji {
display: none; display: none;
} }
` `
// Create stylesheet elements on the website for the classes
var vocabStyleSheet = document.createElement("style") var vocabStyleSheet = document.createElement("style")
var kanjiStyleSheet = document.createElement("style") var kanjiStyleSheet = document.createElement("style")
@ -23,6 +26,7 @@ chrome.storage.local.get(["vocabulary", "kanji", "validUserLevel", "enabled", "e
if(!data.validUserLevel) if(!data.validUserLevel)
return return
// If global setting is enabled, set the stylesheets depending on the other settings
if(data.enabled) if(data.enabled)
{ {
if(data.enabledVocab) if(data.enabledVocab)
@ -45,7 +49,7 @@ chrome.storage.local.get(["vocabulary", "kanji", "validUserLevel", "enabled", "e
var ruby = document.createElement("ruby") var ruby = document.createElement("ruby")
ruby.innerHTML = rubyTags.item(tag).innerHTML ruby.innerHTML = rubyTags.item(tag).innerHTML
// Remove all tags (except for <rb>) // Remove all tags (except for <rb>, <span>)
while(ruby.lastElementChild) while(ruby.lastElementChild)
{ {
if(ruby.lastElementChild.tagName.toLowerCase() === "rb" || if(ruby.lastElementChild.tagName.toLowerCase() === "rb" ||
@ -58,7 +62,8 @@ chrome.storage.local.get(["vocabulary", "kanji", "validUserLevel", "enabled", "e
ruby.removeChild(ruby.lastElementChild) ruby.removeChild(ruby.lastElementChild)
} }
// If the contents of the <ruby> tag are in the word list, remove the <rt> tag // If the contents of the <ruby> tag are in the word list, tag the <rt> tag
// with the correct class
var rtTag = rubyTags.item(tag).getElementsByTagName("rt").item(0) var rtTag = rubyTags.item(tag).getElementsByTagName("rt").item(0)
if(vocabulary.includes(ruby.innerText)) if(vocabulary.includes(ruby.innerText))
rtTag.classList.add("furikani-vocabulary") rtTag.classList.add("furikani-vocabulary")
@ -68,11 +73,12 @@ chrome.storage.local.get(["vocabulary", "kanji", "validUserLevel", "enabled", "e
}) })
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
// One of the switches was checked/unchecked
if(msg.action === "settingsUpdated") if(msg.action === "settingsUpdated")
{ {
// Retrieve current switch states
chrome.storage.local.get(["enabled", "enabledVocab", "enabledKanji"], (data) => { chrome.storage.local.get(["enabled", "enabledVocab", "enabledKanji"], (data) => {
console.log(data) // If everything is disabled, disable all stylsheets
if(!data.enabled) if(!data.enabled)
{ {
vocabStyleSheet.innerHTML = "" vocabStyleSheet.innerHTML = ""
@ -81,6 +87,7 @@ chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
return return
} }
// Otherwise set the kanji and vocab stylesheets depending on their settings
vocabStyleSheet.innerHTML = data.enabledVocab ? vocabStyle : "" vocabStyleSheet.innerHTML = data.enabledVocab ? vocabStyle : ""
kanjiStyleSheet.innerHTML = data.enabledKanji ? kanjiStyle : "" kanjiStyleSheet.innerHTML = data.enabledKanji ? kanjiStyle : ""

View file

@ -9,21 +9,25 @@ const kanjiSetting = document.getElementById("setting-kanji")
// Set popup content // Set popup content
chrome.storage.local.get(["level", "token", "enabled", "enabledVocab", "enabledKanji"], (data) => { chrome.storage.local.get(["level", "token", "enabled", "enabledVocab", "enabledKanji"], (data) => {
// If no token is set, display exlamation mark and checkmark button
if(data.token === undefined) if(data.token === undefined)
{ {
statusField.innerHTML = String.fromCodePoint(0x2757) statusField.innerHTML = String.fromCodePoint(0x2757)
submitButton.innerHTML = String.fromCodePoint(0x2705) submitButton.innerHTML = String.fromCodePoint(0x2705)
submitButton.classList.add("no-token") submitButton.classList.add("no-token")
} }
else else // else display checkmark and reload button
{ {
statusField.innerHTML = String.fromCodePoint(0x2705) statusField.innerHTML = String.fromCodePoint(0x2705)
submitButton.innerHTML = String.fromCodePoint(0x1F501) submitButton.innerHTML = String.fromCodePoint(0x1F501)
} }
// Display the users current WaniKani level
const levelSpan = document.getElementById("level") const levelSpan = document.getElementById("level")
levelSpan.innerHTML = data.level levelSpan.innerHTML = data.level
// If the input field contains text that is not the current token, turn the
// button into a checkmark (else turn it into a repeat button)
inputField.addEventListener("input", () => { inputField.addEventListener("input", () => {
if(inputField.value !== "" && inputField.value !== data.token) if(inputField.value !== "" && inputField.value !== data.token)
{ {
@ -37,13 +41,15 @@ chrome.storage.local.get(["level", "token", "enabled", "enabledVocab", "enabledK
} }
}) })
// Set the switches to thecached values
globalSetting.checked = data.enabled globalSetting.checked = data.enabled
vocabSetting.checked = data.enabledVocab vocabSetting.checked = data.enabledVocab
kanjiSetting.checked = data.enabledKanji kanjiSetting.checked = data.enabledKanji
}) })
// Set the wanikani token // Submit button pressed
submitButton.addEventListener( "click", () => { submitButton.addEventListener( "click", () => {
// If the submit field has a new token, replace the current one with it
if(submitButton.classList.contains("new-token")) if(submitButton.classList.contains("new-token"))
{ {
chrome.storage.local.set({"token": inputField.value}) chrome.storage.local.set({"token": inputField.value})
@ -56,24 +62,27 @@ submitButton.addEventListener( "click", () => {
statusField.innerHTML = String.fromCodePoint(0x23F1) statusField.innerHTML = String.fromCodePoint(0x23F1)
// Sync with wanikani
chrome.runtime.sendMessage("", {type: "sync"}, response => { chrome.runtime.sendMessage("", {type: "sync"}, response => {
if(response.success) if(response.success)
{ {
statusField.innerHTML = String.fromCodePoint(0x2705) statusField.innerHTML = String.fromCodePoint(0x2705)
errorField.innerHTML = "" errorField.innerHTML = ""
} }
else else
{ {
statusField.innerHTML = String.fromCodePoint(0x2757) statusField.innerHTML = String.fromCodePoint(0x2757)
errorField.innerHTML = response.error errorField.innerHTML = response.error
} }
}) })
}) })
// Set settings event listeners // Set settings event listeners
globalSetting.addEventListener("change", () => { globalSetting.addEventListener("change", () => {
chrome.storage.local.set({"enabled": globalSetting.checked}) chrome.storage.local.set({"enabled": globalSetting.checked})
// If the global settings are unchecked, uncheck the other options as well
// and disable them
if(!globalSetting.checked) if(!globalSetting.checked)
{ {
vocabSetting.checked = false vocabSetting.checked = false
@ -82,7 +91,8 @@ globalSetting.addEventListener("change", () => {
vocabSetting.setAttribute("disabled", true) vocabSetting.setAttribute("disabled", true)
kanjiSetting.setAttribute("disabled", true) kanjiSetting.setAttribute("disabled", true)
} }
else // Else restore the values of the switches and activate them agin
else
{ {
chrome.storage.local.get(["enabledVocab", "enabledKanji"], (data) => { chrome.storage.local.get(["enabledVocab", "enabledKanji"], (data) => {
vocabSetting.checked = data.enabledVocab vocabSetting.checked = data.enabledVocab
@ -93,6 +103,7 @@ globalSetting.addEventListener("change", () => {
kanjiSetting.removeAttribute("disabled") kanjiSetting.removeAttribute("disabled")
} }
// Send a message to content script that the switches were updated
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => { chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, {action: "settingsUpdated"}, (r) => {}) chrome.tabs.sendMessage(tabs[0].id, {action: "settingsUpdated"}, (r) => {})
}) })