schoolbox web extension :)
0
fork

Configure Feed

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

refactor: move state and types to storage dir

willow 28eb5b69 5d74a5cb

+113 -116
+1 -1
src/entrypoints/plugins/subheader.ts
··· 1 1 export default function init() { 2 2 defineStPlugin( 3 3 "subheader", 4 - (_id, data, settings) => { 4 + (_id, data) => { 5 5 const style = document.createElement("style"); 6 6 style.classList = "schooltape"; 7 7 style.innerHTML = `
-1
src/entrypoints/popup/App.svelte
··· 9 9 10 10 import { flavors } from "@catppuccin/palette"; 11 11 import { needsRefresh } from "@/utils/storage"; 12 - import { globalSettings } from "#imports"; 13 12 import { RotateCw } from "@lucide/svelte"; 14 13 15 14 const routes = {
-1
src/entrypoints/popup/routes/Home.svelte
··· 1 1 <script lang="ts"> 2 2 import Footer from "../components/Footer.svelte"; 3 3 import Motd from "../components/Motd.svelte"; 4 - import { globalSettings } from "#imports"; 5 4 6 5 let isJune = new Date().getMonth() === 5; 7 6 </script>
-1
src/entrypoints/popup/routes/Plugins.svelte
··· 1 1 <script lang="ts"> 2 2 import Title from "../components/Title.svelte"; 3 - import { globalSettings } from "#imports"; 4 3 import Button from "../components/inputs/Button.svelte"; 5 4 import { Settings } from "@lucide/svelte"; 6 5 import Modal from "../components/Modal.svelte";
-1
src/entrypoints/popup/routes/Snippets.svelte
··· 2 2 import Title from "../components/Title.svelte"; 3 3 import Toggle from "../components/inputs/Toggle.svelte"; 4 4 import TextInput from "../components/inputs/TextInput.svelte"; 5 - import { globalSettings } from "#imports"; 6 5 7 6 let snippetURL = $state(""); 8 7
+1 -4
src/utils/constants.ts
··· 1 - import * as Types from "./types"; 2 - 3 - // Global 4 1 export const EXCLUDE_MATCHES: string[] = ["*://*/learning/quiz/*"]; 5 - export const LOGO_INFO: Record<Types.LogoId, Types.LogoInfo> = { 2 + export const LOGO_INFO: Record<LogoId, LogoInfo> = { 6 3 default: { 7 4 name: "Default", 8 5 url: "default",
+98
src/utils/index.ts
··· 1 1 export * from "./storage"; 2 + 3 + import { flavorEntries } from "@catppuccin/palette"; 4 + 5 + export function injectStyles(styleText: string) { 6 + logger.info(`[content-utils] Injecting styles: ${styleText}`); 7 + const style = document.createElement("style"); 8 + style.textContent = styleText; 9 + style.classList.add("schooltape"); 10 + document.head.append(style); 11 + } 12 + 13 + export function injectCatppuccin(flavour: string, accent: string) { 14 + logger.info(`[content-utils] Injecting Catppuccin: ${flavour} ${accent}`); 15 + let styleText = ":root {"; 16 + const flavourArray = flavorEntries.find((entry) => entry[0] === flavour); 17 + if (flavourArray) { 18 + flavourArray[1].colorEntries.map(([colorName, { hsl }]) => { 19 + styleText += `--ctp-${colorName}: ${hsl.h}, ${hsl.s * 100}%, ${hsl.l * 100}%;\n`; 20 + if (colorName === accent) { 21 + styleText += `--ctp-accent: ${hsl.h}, ${hsl.s * 100}%, ${hsl.l * 100}%;\n`; 22 + } 23 + }); 24 + } 25 + styleText += "}"; 26 + injectStyles(styleText); 27 + } 28 + 29 + export function injectLogo(logo: LogoInfo, setAsFavicon: boolean) { 30 + let url = logo.url; 31 + if (!url.startsWith("http")) { 32 + // eslint-disable-next-line @typescript-eslint/no-explicit-any 33 + url = browser.runtime.getURL(url as any); 34 + } 35 + logger.info(`[content-utils] Injecting Logo: ${logo.name}`); 36 + if (logo.disable) { 37 + return; 38 + } 39 + const style = document.createElement("style"); 40 + style.classList.add("schooltape"); 41 + if (logo.adaptive) { 42 + style.textContent = `a.logo > img { display: none !important; } a.logo { display: flex; align-items: center; justify-content: center; }`; 43 + const span = document.createElement("span"); 44 + span.style.mask = `url("${url}") no-repeat center`; 45 + span.style.maskSize = "100% 100%"; 46 + span.style.backgroundColor = "hsl(var(--ctp-accent))"; 47 + span.style.width = "100%"; 48 + span.style.height = "60px"; 49 + span.style.display = "block"; 50 + window.addEventListener("load", () => { 51 + document.querySelectorAll("a.logo").forEach((logo) => { 52 + const clonedSpan = span.cloneNode(true); 53 + logo.append(clonedSpan); 54 + }); 55 + }); 56 + } else { 57 + style.textContent = `a.logo > img { content: url("${url}"); max-width: 30%; width: 100px; }`; 58 + } 59 + document.head.appendChild(style); 60 + 61 + // inject favicon 62 + if (setAsFavicon) { 63 + let favicon = document.querySelector("link[rel~='icon']") as HTMLLinkElement | null; 64 + if (!favicon) { 65 + favicon = document.createElement("link") as HTMLLinkElement; 66 + favicon.rel = "icon"; 67 + document.head.appendChild(favicon); 68 + } 69 + favicon.href = url; 70 + } 71 + } 72 + 73 + // eslint-disable-next-line @typescript-eslint/no-explicit-any 74 + export function injectStylesheet(url: any) { 75 + logger.info(`[content-utils] Injecting stylesheet: ${url}`); 76 + const link = document.createElement("link"); 77 + link.rel = "stylesheet"; 78 + link.href = browser.runtime.getURL(url); 79 + link.classList.add("schooltape"); 80 + document.head.appendChild(link); 81 + } 82 + 83 + export async function injectUserSnippets(userSnippets: Record<string, UserSnippet>) { 84 + logger.info("[content-utils] Injecting snippets"); 85 + // user snippets 86 + Object.keys(userSnippets).forEach((snippetId) => { 87 + const userSnippet = userSnippets[snippetId]; 88 + if (userSnippet.toggle) { 89 + fetch(`https://gist.githubusercontent.com/${userSnippet.author}/${snippetId}/raw`) 90 + .then((response) => response.text()) 91 + .then((css) => { 92 + const style = document.createElement("style"); 93 + style.textContent = css; 94 + style.classList.add("schooltape"); 95 + document.head.appendChild(style); 96 + }); 97 + } 98 + }); 99 + }
-2
src/utils/state.svelte.ts src/utils/storage/state.svelte.ts
··· 1 - import { WxtStorageItem } from "#imports"; 2 - 3 1 export class StorageState<T> { 4 2 public state; 5 3
+3 -2
src/utils/storage/global.ts
··· 1 - import * as Types from "../types"; 1 + import { StorageState } from "./state.svelte"; 2 + import * as Types from "./types"; 2 3 3 - export const globalSettings: StorageState<Types.Settings> = new StorageState<Types.Settings>( 4 + export const globalSettings = new StorageState<Types.Settings>( 4 5 storage.defineItem<Types.Settings>("local:globalSettings", { 5 6 fallback: { 6 7 global: true,
+4 -3
src/utils/storage/helpers.ts
··· 1 - import * as Types from "../types"; 1 + import { StorageState } from "./state.svelte"; 2 + import * as Types from "./types"; 2 3 3 4 export function createPlugin( 4 5 id: string, ··· 30 31 } 31 32 32 33 export function pluginToggle( 33 - pluginId: string, 34 + pluginId: Types.PluginId, 34 35 settingId: string, 35 36 name: string, 36 37 description: string, ··· 48 49 } 49 50 50 51 export function pluginSlider( 51 - pluginId: string, 52 + pluginId: Types.PluginId, 52 53 settingId: string, 53 54 name: string, 54 55 description: string,
+1
src/utils/storage/index.ts
··· 1 1 export * from "./global"; 2 2 export * from "./plugins"; 3 3 export * from "./snippets"; 4 + export * from "./types";
+2 -2
src/utils/storage/plugins.ts
··· 1 - import * as Types from "../types"; 2 1 import { createPlugin, pluginSlider, pluginToggle } from "./helpers"; 2 + import * as Types from "./types"; 3 3 4 4 export const plugins: Record<Types.PluginId, Types.PluginData> = { 5 5 subheader: createPlugin( ··· 9 9 true, 10 10 { 11 11 openInNewTab: pluginToggle( 12 - "subheaderRevamp", 12 + "subheader", 13 13 "openInNewTab", 14 14 "Open links in new tab", 15 15 "Whether to open the class link in a new tab.",
+1 -1
src/utils/storage/snippets.ts
··· 1 - import * as Types from "../types"; 2 1 import { createSnippet } from "./helpers"; 2 + import * as Types from "./types"; 3 3 4 4 export const snippets: Record<Types.SnippetId, Types.SnippetData> = { 5 5 roundedCorners: createSnippet(
+2
src/utils/types.ts src/utils/storage/types.ts
··· 1 + import { StorageState } from "./state.svelte"; 2 + 1 3 // Global 2 4 export interface Settings { 3 5 global: boolean;
-97
src/utils/utils.ts
··· 1 - import { flavorEntries } from "@catppuccin/palette"; 2 - 3 - export function injectStyles(styleText: string) { 4 - logger.info(`[content-utils] Injecting styles: ${styleText}`); 5 - const style = document.createElement("style"); 6 - style.textContent = styleText; 7 - style.classList.add("schooltape"); 8 - document.head.append(style); 9 - } 10 - 11 - export function injectCatppuccin(flavour: string, accent: string) { 12 - logger.info(`[content-utils] Injecting Catppuccin: ${flavour} ${accent}`); 13 - let styleText = ":root {"; 14 - const flavourArray = flavorEntries.find((entry) => entry[0] === flavour); 15 - if (flavourArray) { 16 - flavourArray[1].colorEntries.map(([colorName, { hsl }]) => { 17 - styleText += `--ctp-${colorName}: ${hsl.h}, ${hsl.s * 100}%, ${hsl.l * 100}%;\n`; 18 - if (colorName === accent) { 19 - styleText += `--ctp-accent: ${hsl.h}, ${hsl.s * 100}%, ${hsl.l * 100}%;\n`; 20 - } 21 - }); 22 - } 23 - styleText += "}"; 24 - injectStyles(styleText); 25 - } 26 - 27 - export function injectLogo(logo: LogoInfo, setAsFavicon: boolean) { 28 - let url = logo.url; 29 - if (!url.startsWith("http")) { 30 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 31 - url = browser.runtime.getURL(url as any); 32 - } 33 - logger.info(`[content-utils] Injecting Logo: ${logo.name}`); 34 - if (logo.disable) { 35 - return; 36 - } 37 - const style = document.createElement("style"); 38 - style.classList.add("schooltape"); 39 - if (logo.adaptive) { 40 - style.textContent = `a.logo > img { display: none !important; } a.logo { display: flex; align-items: center; justify-content: center; }`; 41 - const span = document.createElement("span"); 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 - style.textContent = `a.logo > img { content: url("${url}"); max-width: 30%; width: 100px; }`; 56 - } 57 - document.head.appendChild(style); 58 - 59 - // inject favicon 60 - if (setAsFavicon) { 61 - let favicon = document.querySelector("link[rel~='icon']") as HTMLLinkElement | null; 62 - if (!favicon) { 63 - favicon = document.createElement("link") as HTMLLinkElement; 64 - favicon.rel = "icon"; 65 - document.head.appendChild(favicon); 66 - } 67 - favicon.href = url; 68 - } 69 - } 70 - 71 - // eslint-disable-next-line @typescript-eslint/no-explicit-any 72 - export function injectStylesheet(url: any) { 73 - logger.info(`[content-utils] Injecting stylesheet: ${url}`); 74 - const link = document.createElement("link"); 75 - link.rel = "stylesheet"; 76 - link.href = browser.runtime.getURL(url); 77 - link.classList.add("schooltape"); 78 - document.head.appendChild(link); 79 - } 80 - 81 - export async function injectUserSnippets(userSnippets: Record<string, UserSnippet>) { 82 - logger.info("[content-utils] Injecting snippets"); 83 - // user snippets 84 - Object.keys(userSnippets).forEach((snippetId) => { 85 - const userSnippet = userSnippets[snippetId]; 86 - if (userSnippet.toggle) { 87 - fetch(`https://gist.githubusercontent.com/${userSnippet.author}/${snippetId}/raw`) 88 - .then((response) => response.text()) 89 - .then((css) => { 90 - const style = document.createElement("style"); 91 - style.textContent = css; 92 - style.classList.add("schooltape"); 93 - document.head.appendChild(style); 94 - }); 95 - } 96 - }); 97 - }