schoolbox web extension :)
0
fork

Configure Feed

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

feat(plugins/changeIcon): init

* doesn't work yet, need to change how plugin settings are defined so can have custom settings

willow 46001a2c c745024c

+114 -57
+7 -5
src/entrypoints/plugins.content.ts
··· 1 1 import { defineContentScript } from "#imports"; 2 2 import { EXCLUDE_MATCHES } from "@/utils/constants"; 3 + import changeLogo from "./plugins/changeLogo"; 3 4 import homepageSwitcher from "./plugins/homepageSwitcher"; 4 5 import modernIcons from "./plugins/modernIcons"; 5 6 import progressBar from "./plugins/progressBar"; ··· 13 14 runAt: "document_start", 14 15 excludeMatches: EXCLUDE_MATCHES, 15 16 async main() { 17 + changeLogo(); 18 + homepageSwitcher(); 19 + modernIcons(); 20 + progressBar(); 21 + scrollPeriod(); 22 + scrollSegments(); 16 23 subheader(); 17 - scrollSegments(); 18 - scrollPeriod(); 19 - progressBar(); 20 - modernIcons(); 21 24 tabTitle(); 22 - homepageSwitcher(); 23 25 }, 24 26 });
+86
src/entrypoints/plugins/changeLogo.ts
··· 1 + import { dataAttr, injectInlineStyles, setDataAttr, uninjectInlineStyles } from "@/utils"; 2 + import { LOGO_INFO } from "@/utils/constants"; 3 + import { logger } from "@/utils/logger"; 4 + import { definePlugin } from "@/utils/plugin"; 5 + import type { LogoInfo } from "@/utils/storage"; 6 + 7 + const ID = "changeLogo"; 8 + const PLUGIN_ID = `plugin-${ID}`; 9 + let oldFavicon: string | undefined; 10 + 11 + export default function init() { 12 + definePlugin( 13 + ID, 14 + (settings) => { 15 + // const logo = LOGO_INFO[settings.themeLogo as LogoId]; 16 + // if (settings?.toggle.setAsFavicon) injectFavicon(); 17 + }, 18 + () => {}, 19 + ["#content", "#footer"], 20 + ); 21 + } 22 + 23 + export function injectLogo(logo: LogoInfo, setAsFavicon: boolean): void { 24 + logger.info(`injecting logo: ${logo.name}`); 25 + 26 + if (logo.disable) return; 27 + 28 + let url = logo.url; 29 + if (!url.startsWith("http")) { 30 + // @ts-expect-error unlisted CSS not a PublicPath 31 + url = browser.runtime.getURL(url); 32 + } 33 + 34 + const style = document.createElement("style"); 35 + setDataAttr(style, "logo"); 36 + 37 + if (logo.adaptive) { 38 + // for adaptive logos 39 + style.textContent = `a.logo > img { display: none !important; } a.logo { display: flex; align-items: center; justify-content: center; }`; 40 + const span = document.createElement("span"); 41 + setDataAttr(span, "logo"); 42 + span.style.mask = `url("${url}") no-repeat center`; 43 + span.style.maskSize = "100% 100%"; 44 + span.style.backgroundColor = "hsl(var(--ctp-accent))"; 45 + span.style.width = "100%"; 46 + span.style.height = "60px"; 47 + span.style.display = "block"; 48 + window.addEventListener("load", () => { 49 + document.querySelectorAll("a.logo").forEach((logo) => { 50 + const clonedSpan = span.cloneNode(true); 51 + logo.append(clonedSpan); 52 + }); 53 + }); 54 + } else { 55 + // for normal logos 56 + style.textContent = `a.logo > img { content: url("${url}"); max-width: 30%; width: 100px; }`; 57 + } 58 + document.head.appendChild(style); 59 + } 60 + 61 + function injectFavicon(url: string) { 62 + // inject favicon 63 + let favicon = document.querySelector("link[rel~='icon']") as HTMLLinkElement | null; 64 + 65 + if (!favicon) { 66 + favicon = document.createElement("link") as HTMLLinkElement; 67 + favicon.rel = "icon"; 68 + document.head.appendChild(favicon); 69 + } 70 + 71 + oldFavicon = favicon?.href; 72 + favicon.href = url; 73 + } 74 + 75 + function uninjectFavicon() {} 76 + 77 + export function uninjectLogo(originalFavicon: string) { 78 + logger.info("uninjecting logo..."); 79 + for (const el of document.querySelectorAll(dataAttr("logo"))) { 80 + el.parentElement?.removeChild(el); 81 + } 82 + 83 + // uninject favicon 84 + const favicon = document.querySelector<HTMLLinkElement>("link[rel~='icon']"); 85 + if (favicon) favicon.href = originalFavicon; 86 + }
+4 -6
src/entrypoints/start.content.ts
··· 2 2 import { 3 3 hasChanged, 4 4 injectCatppuccin, 5 - injectLogo, 6 5 injectStylesheet, 7 6 injectUserSnippet, 8 7 uninjectCatppuccin, ··· 10 9 uninjectUserSnippet, 11 10 } from "@/utils"; 12 11 import { EXCLUDE_MATCHES, LOGO_INFO } from "@/utils/constants"; 13 - import type { LogoId, Settings } from "@/utils/storage"; 12 + import type { Settings } from "@/utils/storage"; 14 13 import { globalSettings, schoolboxUrls } from "@/utils/storage"; 15 14 import type { WatchCallback } from "wxt/utils/storage"; 16 15 import cssUrl from "./catppuccin.css?url"; ··· 38 37 }; 39 38 40 39 const updateUserSnippets: WatchCallback<Settings> = (newValue, oldValue) => { 41 - // if global or userSnippets were changed 40 + // if global or userSnippets was changed 42 41 if (hasChanged(newValue, oldValue, ["global", "userSnippets"])) { 43 42 for (const [id, userSnippet] of Object.entries(newValue.userSnippets)) { 44 43 if (newValue.global && newValue.snippets && userSnippet.toggle) { ··· 56 55 57 56 // storage listeners for hot reload 58 57 globalSettings.storage.watch((newValue, oldValue) => { 58 + if (!urls.includes(window.location.origin)) return; 59 + 59 60 updateThemes(newValue, oldValue); 60 61 updateUserSnippets(newValue, oldValue); 61 62 }); ··· 66 67 injectThemes(); 67 68 injectCatppuccin(); 68 69 } 69 - 70 - // inject logo 71 - injectLogo(LOGO_INFO[settings.themeLogo as LogoId], settings.themeLogoAsFavicon); 72 70 73 71 // inject user snippets 74 72 if (settings.snippets) {
-44
src/utils/index.ts
··· 48 48 uninjectInlineStyles("catppuccin"); 49 49 } 50 50 51 - export function injectLogo(logo: LogoInfo, setAsFavicon: boolean) { 52 - let url = logo.url; 53 - if (!url.startsWith("http")) { 54 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 55 - url = browser.runtime.getURL(url as any); 56 - } 57 - logger.info(`injecting logo: ${logo.name}`); 58 - if (logo.disable) { 59 - return; 60 - } 61 - const style = document.createElement("style"); 62 - style.classList.add("schooltape"); 63 - if (logo.adaptive) { 64 - style.textContent = `a.logo > img { display: none !important; } a.logo { display: flex; align-items: center; justify-content: center; }`; 65 - const span = document.createElement("span"); 66 - span.style.mask = `url("${url}") no-repeat center`; 67 - span.style.maskSize = "100% 100%"; 68 - span.style.backgroundColor = "hsl(var(--ctp-accent))"; 69 - span.style.width = "100%"; 70 - span.style.height = "60px"; 71 - span.style.display = "block"; 72 - window.addEventListener("load", () => { 73 - document.querySelectorAll("a.logo").forEach((logo) => { 74 - const clonedSpan = span.cloneNode(true); 75 - logo.append(clonedSpan); 76 - }); 77 - }); 78 - } else { 79 - style.textContent = `a.logo > img { content: url("${url}"); max-width: 30%; width: 100px; }`; 80 - } 81 - document.head.appendChild(style); 82 - 83 - // inject favicon 84 - if (setAsFavicon) { 85 - let favicon = document.querySelector("link[rel~='icon']") as HTMLLinkElement | null; 86 - if (!favicon) { 87 - favicon = document.createElement("link") as HTMLLinkElement; 88 - favicon.rel = "icon"; 89 - document.head.appendChild(favicon); 90 - } 91 - favicon.href = url; 92 - } 93 - } 94 - 95 51 export function injectStylesheet(url: string, id: string) { 96 52 // check if stylesheet has already been injected 97 53 const existingLink = document.querySelector(dataAttr(`stylesheet-${id}`));
+17
src/utils/storage/plugins.ts
··· 45 45 description: "Displays a progress bar below the timetable to show the time of the day.", 46 46 default: true, 47 47 }, 48 + changeLogo: { 49 + name: "Change Logo", 50 + description: "Changes the Schoolbox logo to a logo of your choice", 51 + default: true, 52 + settings: { 53 + // logo: { 54 + // type: "logos", 55 + // default: { logo: "schooltape" }, 56 + // }, 57 + setAsFavicon: { 58 + type: "toggle", 59 + name: "Set as favicon", 60 + description: "Whether to set the logo as the tab favicon.", 61 + default: { toggle: true }, 62 + }, 63 + }, 64 + }, 48 65 modernIcons: { 49 66 name: "Modern Icons", 50 67 description: "Modernise the icons across Schoolbox.",
-2
src/utils/storage/types.ts
··· 11 11 12 12 themeFlavour: string; 13 13 themeAccent: string; 14 - themeLogo: LogoId; 15 - themeLogoAsFavicon: boolean; 16 14 17 15 userSnippets: Record<string, UserSnippet>; 18 16 }