diff --git a/api/main.js b/api/main.js index eed642eb..f914a8f0 100644 --- a/api/main.js +++ b/api/main.js @@ -46,9 +46,7 @@ ScratchTools.waitForElements = function (selector, callback, id, rework) { } }; -var stylesDiv = document.createElement("div"); -stylesDiv.className = "scratchtools-styles-div"; -document.head.appendChild(stylesDiv); +var stylesDiv = document.querySelector("div.scratchtools-styles-div"); ScratchTools.waitForElements("head > *", function (el) { if (el !== stylesDiv) { document.head.appendChild(stylesDiv); diff --git a/extras/background.js b/extras/background.js index bc1e4e36..1b40d9a7 100644 --- a/extras/background.js +++ b/extras/background.js @@ -1,4 +1,9 @@ +let cachedStorage; +let cachedStyles; + chrome.runtime.onInstalled.addListener(async function (object) { + cachedStorage = (await chrome.storage.sync.get("features"))?.features || ""; + cachedStyles = await getEnabledStyles(); try { var featureData = await (await fetch("/features/features.json")).json(); } catch (err) { @@ -79,6 +84,15 @@ chrome.runtime.onInstalled.addListener(async function (object) { } }); +chrome.storage.onChanged.addListener(async function (changes, namespace) { + for (let [key, { oldValue, newValue }] of Object.entries(changes)) { + if (key === "features") { + cachedStorage = newValue; + cachedStyles = await getEnabledStyles(); + } + } +}); + chrome.tabs.onUpdated.addListener(async function (tabId, info) { var tab = await chrome.tabs.get(tabId); if (tab?.url?.startsWith("https://scratch.mit.edu/")) { @@ -450,29 +464,6 @@ chrome.tabs.onUpdated.addListener(async function (tabId, info) { world: newData.world?.toUpperCase() || "MAIN", }); } - } - }); - newData.styles?.forEach(function (style) { - if (new URL(tab.url).pathname.match(style.runOn)) { - chrome.scripting.executeScript({ - args: [ - data[el].id, - chrome.runtime.getURL( - `/features/${data[el]["id"]}/${style.file}` - ), - ], - target: { tabId: tabId }, - func: insertCSS, - world: "MAIN", - }); - function insertCSS(feature, path) { - var link = document.createElement("link"); - link.rel = "stylesheet"; - link.href = path; - link.dataset.feature = feature; - document.querySelector(".scratchtools-styles-div").appendChild(link); - } - } }); } else { chrome.scripting.executeScript({ @@ -520,7 +511,7 @@ chrome.runtime.onMessageExternal.addListener(async function ( storagePromises.forEach(function (promise) { if (promise.key === key && !promise.resolved) { promise.resolve(value); - promise.resolved = true + promise.resolved = true; } }); } @@ -528,11 +519,34 @@ chrome.runtime.onMessageExternal.addListener(async function ( } }); +async function getEnabledStyles() { + var allStyles = []; + var data = (await (await fetch(`/features/features.json`)).json()).filter( + (el) => el.version === 2 && cachedStorage.includes(el.id) + ); + for (var i in data) { + var feature = data[i]; + var styles = ( + await (await fetch(`/features/${feature.id}/data.json`)).json() + ).styles; + if (styles) { + for (var i2 in styles) { + styles[i2].feature = feature + allStyles.push(styles[i2]); + } + } + } + return allStyles; +} + chrome.runtime.onMessage.addListener(async function ( msg, sender, sendResponse ) { + if (msg.action === "getStyles") { + sendResponse({ data: cachedStyles }); + } if (msg?.text === "get-logged-in-user") { sendResponse(true); const data = await ( diff --git a/extras/inject-styles.js b/extras/inject-styles.js new file mode 100644 index 00000000..744da314 --- /dev/null +++ b/extras/inject-styles.js @@ -0,0 +1,35 @@ +async function getAllUserstyles() { + var div = document.createElement("div"); + div.className = "scratchtools-styles-div"; + document.head.appendChild(div); + var styles = await getStyles(); + styles.forEach(function (style) { + if (window.location.pathname.match(style.runOn)) { + var link = document.createElement("link"); + link.rel = "stylesheet"; + link.href = chrome.runtime.getURL(`/features/${style.feature.id}/${style.file}`); + link.dataset.feature = style.feature.id; + document.querySelector(".scratchtools-styles-div").appendChild(link); + } + }); +} + +var injectStylesWaitForHead = new MutationObserver(injectStyles); +injectStylesWaitForHead.observe(document.querySelector("html"), { + childList: true, +}); + +async function injectStyles() { + if (document.head) { + injectStylesWaitForHead.disconnect(); + getAllUserstyles(); + } +} + +async function getStyles() { + return new Promise((resolve, reject) => { + chrome.runtime.sendMessage({ action: "getStyles" }, function (response) { + resolve(response.data || ""); + }); + }); +} diff --git a/manifest.json b/manifest.json index a1b33086..a7a1ca34 100644 --- a/manifest.json +++ b/manifest.json @@ -21,10 +21,25 @@ "48": "/extras/icons/icon48.png", "128": "/extras/icons/icon128.png" }, - "web_accessible_resources": [{ - "resources": ["features/*", "/extras/feature/index.html", "/api/*", "/extras/icons/*"], - "matches": ["https://scratch.mit.edu/*"] - }], + "content_scripts": [ + { + "matches": ["https://scratch.mit.edu/*"], + "run_at": "document_start", + "js": ["extras/inject-styles.js"], + "all_frames": true + } + ], + "web_accessible_resources": [ + { + "resources": [ + "features/*", + "/extras/feature/index.html", + "/api/*", + "/extras/icons/*" + ], + "matches": ["https://scratch.mit.edu/*"] + } + ], "host_permissions": ["https://scratch.mit.edu/"], "browser_specific_settings": { "gecko": {