schoolbox web extension :)
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(storage): pass parsed settings to plugin injectors

willow 47450f78 fdbaccaa

+53 -27
+2 -3
src/entrypoints/plugins/homepageSwitcher.ts
··· 4 4 export default function init() { 5 5 definePlugin( 6 6 "homepageSwitcher", 7 - (_id, data, settings) => { 7 + (_id, _data, settings) => { 8 8 const logos = Array.from(document.getElementsByClassName("logo")) as HTMLAnchorElement[]; 9 9 logos.forEach((logo) => { 10 10 logo.addEventListener("click", async function (e) { 11 11 if (window.location.pathname === "/") return; 12 12 e.preventDefault(); 13 13 const tab = logos[0].href; 14 - const closeCurrentTab = await settings?.closeCurrentTab.state.storage.getValue(); 15 - if (closeCurrentTab?.toggle === true) { 14 + if (settings?.toggle.closeCurrentTab === true) { 16 15 window.close(); 17 16 } 18 17 browser.runtime.sendMessage({ toTab: tab });
+2 -2
src/entrypoints/plugins/modernIcons/index.ts
··· 5 5 export default function init() { 6 6 definePlugin( 7 7 "modernIcons", 8 - async (_id, data) => { 8 + async (_id, _data, settings) => { 9 9 // [className, iconName] (material icons) 10 10 const icons = { 11 11 "icon-teacher": "school", ··· 72 72 injectStyles(styleText); 73 73 74 74 for (const [className, iconName] of Object.entries(icons)) { 75 - insertIcon(className, iconName, settings.toggle.filled); 75 + insertIcon(className, iconName, settings?.toggle.filled ?? false); 76 76 } 77 77 }, 78 78 ["nav.tab-bar .top-menu", "#overflow-nav"],
+4 -5
src/entrypoints/plugins/scrollPeriod.ts
··· 4 4 export default function init() { 5 5 definePlugin( 6 6 "scrollPeriod", 7 - async (_id, data) => { 7 + async (_id, _data, settings) => { 8 8 const timetable = document.querySelector("[data-timetable-container] div.scrollable"); 9 9 10 10 if (window.location.pathname === "/" && document.getElementsByClassName("timetable")[0]) { 11 11 updateScrollbar(); 12 12 13 - const cooldownDuration = await data.settings?.slider?.cooldownDuration?.slider?.storage?.getValue(); 14 - const resetCooldownOnMouseMove = 15 - await data.settings?.toggle?.resetCooldownOnMouseMove?.toggle?.storage?.getValue(); 13 + const cooldownDuration = settings?.slider.cooldownDuration; 14 + const resetCooldownOnMouseMove = settings?.toggle.resetCooldownOnMouseMove; 16 15 17 16 let interval: string | number | NodeJS.Timeout | undefined; 18 17 function start() { ··· 27 26 28 27 start(); 29 28 30 - if (resetCooldownOnMouseMove?.toggle === true) { 29 + if (resetCooldownOnMouseMove === true) { 31 30 document.addEventListener("mousemove", reset); 32 31 } 33 32 }
+3 -3
src/entrypoints/plugins/subheader.ts
··· 4 4 export default function init() { 5 5 definePlugin( 6 6 "subheader", 7 - (_id, data) => { 7 + (_id, _data, settings) => { 8 8 const style = document.createElement("style"); 9 9 style.classList = "schooltape"; 10 10 style.innerHTML = ` ··· 16 16 color: inherit; 17 17 } 18 18 `; 19 + 19 20 document.head.appendChild(style); 20 21 21 22 if (window.location.pathname === "/" && document.getElementsByClassName("timetable")[0]) { ··· 63 64 if (!periodLink) { 64 65 periodLink = document.createElement("a"); 65 66 66 - const openInNewTab = settings.openInNewTab.state.storage.getValue().toggle; 67 - periodLink.target = openInNewTab ? "_blank" : "_self"; 67 + periodLink.target = settings?.toggle.openInNewTab ? "_blank" : "_self"; 68 68 periodSpan.appendChild(periodLink); 69 69 } 70 70 periodLink.href = period.data.link;
+2 -3
src/entrypoints/plugins/tabTitle.ts
··· 3 3 export default function init() { 4 4 definePlugin( 5 5 "tabTitle", 6 - async (_id, data) => { 6 + async (_id, _data, settings) => { 7 7 const path = window.location.pathname; 8 8 const titleMap: { [key: string]: string } = { 9 9 "/": "Homepage", ··· 37 37 } else if (path.includes("/learning/due/")) { 38 38 document.title = "Due Work"; 39 39 } else if (path.includes("/homepage/")) { 40 - const showPrefix = (await data.settings?.toggle?.showSubjectPrefix?.toggle?.storage?.getValue())?.toggle; 41 - if (showPrefix === false) { 40 + if (settings?.toggle.showSubjectPrefix === false) { 42 41 document.title = document.getElementsByTagName("h1")[0].innerText.replace(/^.*- /, ""); 43 42 } else { 44 43 document.title = document.getElementsByTagName("h1")[0].innerText;
+1 -1
src/utils/index.ts
··· 4 4 import type { LogoInfo, UserSnippet } from "./storage"; 5 5 6 6 export function injectStyles(styleText: string) { 7 - logger.info(`[content-utils] Injecting styles: ${styleText}`); 7 + logger.info(`[content-utils] Injecting styles`); 8 8 const style = document.createElement("style"); 9 9 style.textContent = styleText; 10 10 style.classList.add("schooltape");
+37 -8
src/utils/plugin.ts
··· 1 1 import { logger } from "./logger"; 2 - import type { PluginData, PluginId, PluginSetting } from "./storage"; 2 + import type { PluginData, PluginId, PluginSetting, Slider } from "./storage"; 3 3 import { globalSettings, plugins, schoolboxUrls } from "./storage"; 4 4 5 5 export async function definePlugin( 6 6 pluginId: PluginId, 7 - injectLogic: (id: PluginId, data: PluginData, settings?: Record<string, PluginSetting>) => Promise<void> | void, 7 + injectLogic: ( 8 + id: PluginId, 9 + data: PluginData, 10 + settings?: { 11 + toggle: Record<string, boolean>; 12 + slider: Record<string, Slider>; 13 + }, 14 + ) => Promise<void> | void, 8 15 elementsToWaitFor: string[] = [], 9 16 ) { 10 17 const plugin = await plugins[pluginId].toggle.storage.getValue(); ··· 17 24 if (plugin && typeof window !== "undefined" && urls.includes(window.location.origin)) { 18 25 if (settings.global && settings.plugins && plugin.toggle) { 19 26 const injectPlugin = () => { 27 + injectLogic(pluginId, plugins[pluginId], getSettingsValues(plugins[pluginId].settings!)); 28 + }; 29 + 30 + const loadPlugin = () => { 20 31 // wait for elements to be loaded 21 32 if (elementsToWaitFor.length > 0) { 22 33 const observer = new MutationObserver((_mutations, observer) => { ··· 24 35 if (allElementsPresent) { 25 36 observer.disconnect(); 26 37 logger.info(`all elements present, injecting plugin: ${plugins[pluginId].name}`); 27 - injectLogic(pluginId, plugins[pluginId], plugins[pluginId]?.settings); 38 + injectPlugin(); 28 39 } 29 40 }); 30 41 31 42 observer.observe(document.body, { childList: true, subtree: true }); 32 43 33 - // Check if elements are already present 44 + // check if elements are already present 34 45 const allElementsPresent = elementsToWaitFor.every((selector) => document.querySelector(selector) !== null); 35 46 if (allElementsPresent) { 36 47 observer.disconnect(); 37 48 logger.info(`all elements already present, injecting plugin: ${plugins[pluginId].name}`); 38 - injectLogic(pluginId, plugins[pluginId]); 49 + injectPlugin(); 39 50 } 40 51 } else { 41 52 // no elements to wait for 42 53 logger.info(`injecting plugin: ${plugins[pluginId].name}`); 43 - injectLogic(pluginId, plugins[pluginId]); 54 + injectPlugin(); 44 55 } 45 56 }; 46 57 47 58 if (document.body) { 48 - injectPlugin(); 59 + loadPlugin(); 49 60 } else { 50 - document.addEventListener("DOMContentLoaded", injectPlugin); 61 + document.addEventListener("DOMContentLoaded", loadPlugin); 51 62 } 52 63 } 53 64 } 54 65 } 66 + 67 + function getSettingsValues(settings: Record<string, PluginSetting>) { 68 + logger.info("Getting settings values for settings:", settings); 69 + const result: { 70 + toggle: Record<string, boolean>; 71 + slider: Record<string, Slider>; 72 + } = { toggle: {}, slider: {} }; 73 + for (const [key, setting] of Object.entries(settings)) { 74 + if (setting.type === "toggle") { 75 + const value = setting.state.get(); 76 + result.toggle[key] = value.toggle; 77 + } else if (setting.type === "slider") { 78 + const value = setting.state.get(); 79 + result.slider[key] = value; 80 + } 81 + } 82 + return result; 83 + }
+2 -2
src/utils/storage/plugins.ts
··· 2 2 import { StorageState } from "./state.svelte"; 3 3 import type * as Types from "./types"; 4 4 5 - const pluginConfig: Record<Types.PluginId, Types.PluginConfig> = { 5 + export const pluginConfig: Record<Types.PluginId, Types.PluginConfig> = { 6 6 subheader: { 7 7 name: "Subheader Revamp", 8 8 description: "Adds a clock and current period info to the subheader.", ··· 84 84 }, 85 85 }, 86 86 }, 87 - }; 87 + } as const; 88 88 89 89 export const plugins = buildPluginsFromConfig(pluginConfig); 90 90