schoolbox web extension :)
1import { browser, defineContentScript } from "#imports"; 2import { 3 hasChanged, 4 injectCatppuccin, 5 injectLogo, 6 injectStylesheet, 7 injectUserSnippet, 8 uninjectCatppuccin, 9 uninjectStylesheet, 10 uninjectUserSnippet, 11} from "@/utils"; 12import { EXCLUDE_MATCHES, LOGO_INFO } from "@/utils/constants"; 13import type { LogoId, Settings } from "@/utils/storage"; 14import { globalSettings, schoolboxUrls } from "@/utils/storage"; 15import type { WatchCallback } from "wxt/utils/storage"; 16import cssUrl from "./catppuccin.css?url"; 17 18export default defineContentScript({ 19 matches: ["<all_urls>"], 20 cssInjectionMode: "manual", 21 runAt: "document_start", 22 excludeMatches: EXCLUDE_MATCHES, 23 async main() { 24 const settings = await globalSettings.get(); 25 const urls = (await schoolboxUrls.get()).urls; 26 27 const updateThemes: WatchCallback<Settings> = (newValue, oldValue) => { 28 // if global or themes was changed 29 if (hasChanged(newValue, oldValue, ["global", "themes", "themeFlavour", "themeAccent"])) { 30 if (newValue.global && newValue.themes) { 31 injectThemes(); 32 injectCatppuccin(); 33 } else { 34 uninjectThemes(); 35 uninjectCatppuccin(); 36 } 37 } 38 }; 39 40 const updateUserSnippets: WatchCallback<Settings> = (newValue, oldValue) => { 41 // if global or userSnippets were changed 42 if (hasChanged(newValue, oldValue, ["global", "userSnippets"])) { 43 // uninject removed snippets 44 if (oldValue) { 45 for (const id of Object.keys(oldValue.userSnippets)) { 46 if (!newValue.userSnippets[id]) { 47 uninjectUserSnippet(id); 48 } 49 } 50 } 51 52 // inject/uninject current snippets 53 for (const [id, userSnippet] of Object.entries(newValue.userSnippets)) { 54 if (newValue.global && newValue.snippets && userSnippet.toggle) { 55 injectUserSnippet(id); 56 } else { 57 uninjectUserSnippet(id); 58 } 59 } 60 } 61 }; 62 63 // @ts-expect-error unlisted CSS not a PublicPath 64 const injectThemes = () => injectStylesheet(browser.runtime.getURL(cssUrl), "themes"); 65 const uninjectThemes = () => uninjectStylesheet("themes"); 66 67 // storage listeners for hot reload 68 globalSettings.watch((newValue, oldValue) => { 69 updateThemes(newValue, oldValue); 70 updateUserSnippets(newValue, oldValue); 71 }); 72 73 if (settings.global && urls.includes(window.location.origin)) { 74 // inject themes 75 if (settings.themes) { 76 injectThemes(); 77 injectCatppuccin(); 78 } 79 80 // inject logo 81 injectLogo(LOGO_INFO[settings.themeLogo as LogoId], settings.themeLogoAsFavicon); 82 83 // inject user snippets 84 if (settings.snippets) { 85 const userSnippets = (await globalSettings.get()).userSnippets; 86 for (const [id, snippet] of Object.entries(userSnippets)) { 87 if (snippet.toggle) { 88 injectUserSnippet(id); 89 } 90 } 91 } 92 93 // update icon 94 browser.runtime.sendMessage({ updateIcon: true }); 95 } 96 }, 97});