schoolbox web extension :)
0
fork

Configure Feed

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

feat(themes): hot reload

willow bd13a9fb c7ed1d74

+47 -30
+9 -6
src/entrypoints/start.content.ts
··· 7 7 injectUserSnippet, 8 8 uninjectUserSnippet, 9 9 hasChanged, 10 + uninjectCatppuccin, 10 11 } from "@/utils"; 11 12 import { EXCLUDE_MATCHES, LOGO_INFO } from "@/utils/constants"; 12 13 import type { LogoId, Settings } from "@/utils/storage"; ··· 25 26 26 27 const updateThemes: WatchCallback<Settings> = (newValue, oldValue) => { 27 28 // if global or themes was changed 28 - if (hasChanged(newValue, oldValue, ["global", "themes"])) { 29 + if (hasChanged(newValue, oldValue, ["global", "themes", "themeFlavour", "themeAccent"])) { 29 30 if (newValue.global && newValue.themes) { 30 31 injectThemes(); 32 + injectCatppuccin(); 31 33 } else { 32 34 uninjectThemes(); 35 + uninjectCatppuccin(); 33 36 } 34 37 } 35 38 }; ··· 54 57 // inject themes 55 58 if (settings.themes) { 56 59 injectThemes(); 57 - 58 - // inject CSS variables 59 - injectCatppuccin(settings.themeFlavour, settings.themeAccent); 60 + injectCatppuccin(); 60 61 } 61 62 62 63 // inject logo ··· 65 66 // inject user snippets 66 67 if (settings.snippets) { 67 68 const userSnippets = globalSettings.get().userSnippets; 68 - for (const id of Object.keys(userSnippets)) { 69 - injectUserSnippet(id); 69 + for (const [id, snippet] of Object.entries(userSnippets)) { 70 + if (snippet.toggle) { 71 + injectUserSnippet(id); 72 + } 70 73 } 71 74 } 72 75
+38 -24
src/utils/index.ts
··· 4 4 import { globalSettings } from "./storage"; 5 5 import type { LogoInfo } from "./storage"; 6 6 7 - // TODO: uninjectStyles 8 - export function injectStyles(styleText: string) { 9 - logger.info(`injecting styles`); 7 + function schooltapeQuerySelector(id: string) { 8 + return document.querySelector(`[data-schooltape="${id}"]`); 9 + } 10 + 11 + export function injectStyles(styleText: string, id: string) { 12 + logger.info(`injecting styles with id ${id}`); 10 13 const style = document.createElement("style"); 11 14 style.textContent = styleText; 12 - style.classList.add("schooltape"); 15 + style.dataset.schooltape = `inline-${id}`; 13 16 document.head.append(style); 17 + // logger.info(`injected styles with id ${id}`); 14 18 } 15 19 16 - export function injectCatppuccin(flavour: string, accent: string) { 20 + export function uninjectStyles(id: string) { 21 + logger.info(`uninjecting styles with id ${id}`); 22 + const style = schooltapeQuerySelector(`inline-${id}`); 23 + if (style) { 24 + document.head.removeChild(style); 25 + // logger.info(`uninjected styles with id ${id}`); 26 + } else { 27 + // logger.warn(`styles with id ${id} not found, aborting`) 28 + } 29 + } 30 + 31 + export function injectCatppuccin() { 32 + const settings = globalSettings.get(); 33 + const flavour = settings.themeFlavour; 34 + const accent = settings.themeAccent; 35 + 17 36 logger.info(`injecting catppuccin: ${flavour} ${accent}`); 18 37 let styleText = ":root {"; 19 38 const flavourArray = flavorEntries.find((entry) => entry[0] === flavour); ··· 26 45 }); 27 46 } 28 47 styleText += "}"; 29 - injectStyles(styleText); 48 + injectStyles(styleText, "catppuccin"); 49 + } 50 + 51 + export function uninjectCatppuccin() { 52 + uninjectStyles("catppuccin"); 30 53 } 31 54 32 55 export function injectLogo(logo: LogoInfo, setAsFavicon: boolean) { ··· 76 99 // eslint-disable-next-line @typescript-eslint/no-explicit-any 77 100 export function injectStylesheet(url: any, id: string) { 78 101 // check if stylesheet has already been injected 79 - const existingLink = document.querySelector(`link[data-schooltape="${id}"]`); 102 + const existingLink = schooltapeQuerySelector(`stylesheet-${id}`); 80 103 if (existingLink) { 81 104 logger.info(`stylesheet with id ${id} already injected, aborting`); 82 105 return; ··· 87 110 const link = document.createElement("link"); 88 111 link.rel = "stylesheet"; 89 112 link.href = browser.runtime.getURL(url); 90 - link.dataset.schooltape = id; 113 + link.dataset.schooltape = `stylesheet-${id}`; 91 114 document.head.appendChild(link); 92 115 } 93 116 94 117 export function uninjectStylesheet(id: string) { 95 118 logger.info(`uninjecting stylesheet with id ${id}`); 96 - const link = document.querySelector(`link[data-schooltape="${id}"]`); 119 + const link = schooltapeQuerySelector(`stylesheet-${id}`); 97 120 if (link) { 98 121 document.head.removeChild(link); 99 122 } else { ··· 114 137 115 138 if (snippet.toggle === true) { 116 139 // check not already injected 117 - const style = document.querySelector(`style[data-schooltape="userSnippet-${id}"]`); 140 + const style = document.querySelector(`userSnippet-${id}`); 118 141 if (style) { 119 142 logger.info(`user snippet with id ${id} already injected, aborting`); 120 143 return; ··· 135 158 136 159 export function uninjectUserSnippet(id: string) { 137 160 logger.info(`uninjecting user snippet with id ${id}`); 138 - const style = document.querySelector(`style[data-schooltape="userSnippet-${id}"]`); 161 + const style = document.querySelector(`userSnippet-${id}`); 139 162 if (style) { 140 163 document.head.removeChild(style); 141 164 logger.info(`uninjected user snippet with id ${id}`); ··· 144 167 } 145 168 } 146 169 147 - function getChangedValues<T extends Record<string, any>>(newValue: T, oldValue: T) { 148 - const changedKeys = []; 170 + export function hasChanged<T extends Record<string, any>>(newValue: T, oldValue: T, keys: (keyof T)[]) { 171 + const changed: (keyof T)[] = []; 149 172 150 173 for (const key in newValue) { 151 174 if (newValue.hasOwnProperty(key) && oldValue[key] !== newValue[key]) { 152 - changedKeys.push(key); 175 + changed.push(key); 153 176 } 154 177 } 155 178 156 - return changedKeys; 157 - } 158 - 159 - function includesSome(array: string[], items: string[]) { 160 - return items.some((item) => array.includes(item)); 161 - } 162 - 163 - export function hasChanged<T extends Record<string, any>>(newValue: T, oldValue: T, keys: string[]) { 164 - const changed = getChangedValues(newValue, oldValue); 165 - return includesSome(changed, keys); 179 + return keys.some((item) => changed.includes(item)); 166 180 }