···11+import type { Browser } from "#imports";
22+import { browser, defineBackground, storage } from "#imports";
33+import { logger } from "@/utils/logger";
44+import { globalSettings, updated } from "@/utils/storage";
15import semver from "semver";
2637export default defineBackground(() => {
+5
src/entrypoints/end.content.ts
···11+import { browser, defineContentScript } from "#imports";
22+import { EXCLUDE_MATCHES } from "@/utils/constants";
33+import { logger } from "@/utils/logger";
44+import { globalSettings, schoolboxUrls } from "@/utils/storage";
55+16export default defineContentScript({
27 matches: ["<all_urls>"],
38 runAt: "document_end",
+2
src/entrypoints/plugins.content.ts
···11+import { defineContentScript } from "#imports";
22+import { EXCLUDE_MATCHES } from "@/utils/constants";
13import homepageSwitcher from "./plugins/homepageSwitcher";
24import modernIcons from "./plugins/modernIcons";
35import progressBar from "./plugins/progressBar";
···11+import { browser, defineContentScript } from "#imports";
22+import { injectCatppuccin, injectLogo, injectStylesheet, injectUserSnippets } from "@/utils";
33+import { EXCLUDE_MATCHES, LOGO_INFO } from "@/utils/constants";
44+import type { LogoId } from "@/utils/storage";
55+import { globalSettings, schoolboxUrls } from "@/utils/storage";
16import cssUrl from "./catppuccin.css?url";
2738export default defineContentScript({
+2-3
src/utils/constants.ts
···11-import * as Types from "./types";
11+import type { LogoId, LogoInfo } from "./storage";
2233-// Global
43export const EXCLUDE_MATCHES: string[] = ["*://*/learning/quiz/*"];
55-export const LOGO_INFO: Record<Types.LogoId, Types.LogoInfo> = {
44+export const LOGO_INFO: Record<LogoId, LogoInfo> = {
65 default: {
76 name: "Default",
87 url: "default",
+2
src/utils/periodUtils.ts
···11// these utility functions are intended to be used on the dashboard, as that is where the timetable is displayed
2233+import { logger } from "./logger";
44+35interface PeriodHeader {
46 name: string;
57 time: {
···11-import { WxtStorageItem } from "#imports";
11+import type { WxtStorageItem } from "#imports";
22+import { needsRefresh } from "./global";
2334export class StorageState<T> {
45 public state;
-271
src/utils/storage.ts
···11-import { StorageState } from "./state.svelte";
22-import * as Types from "./types";
33-44-// Global
55-export const globalSettings: StorageState<Types.Settings> = new StorageState<Types.Settings>(
66- storage.defineItem<Types.Settings>("local:globalSettings", {
77- fallback: {
88- global: true,
99- plugins: true,
1010- themes: true,
1111- snippets: true,
1212-1313- themeFlavour: "mocha",
1414- themeAccent: "mauve",
1515- themeLogo: "schooltape-rainbow",
1616- themeLogoAsFavicon: false,
1717-1818- userSnippets: {},
1919- },
2020- }),
2121- true,
2222-);
2323-2424-export const needsRefresh = new StorageState(
2525- storage.defineItem<boolean>("local:needsRefresh", {
2626- fallback: false,
2727- }),
2828-);
2929-3030-// whether schooltape was recently updated
3131-export const updated = new StorageState(
3232- storage.defineItem<Types.UpdatedBadges>("local:updated", {
3333- version: 2,
3434- fallback: {
3535- icon: false,
3636- changelog: false,
3737- },
3838- migrations: {
3939- 2: async () => {
4040- // reset to fallback
4141- await storage.removeItem("local:updated");
4242- },
4343- },
4444- }),
4545-);
4646-4747-// message of the day
4848-export const motd = new StorageState(
4949- storage.defineItem<Types.Motd>("local:motd", {
5050- fallback: {
5151- motd: "Free and <a href='https://github.com/schooltape/schooltape' class='text-(--ctp-accent)'> open source</a>!",
5252- },
5353- }),
5454-);
5555-5656-export const schoolboxUrls = new StorageState(
5757- storage.defineItem<Types.SchoolboxUrls>("local:urls", {
5858- version: 1,
5959- fallback: {
6060- urls: ["https://help.schoolbox.com.au"],
6161- },
6262- }),
6363-);
6464-6565-// Plugins
6666-function createPlugin(
6767- id: string,
6868- name: string,
6969- description: string,
7070- fallbackToggle: boolean,
7171- settings?: Types.PluginSettings,
7272-) {
7373- const plugin: Types.PluginData = {
7474- toggle: new StorageState(
7575- storage.defineItem<Types.ItemGeneric>(`local:plugin-${id}`, {
7676- fallback: {
7777- toggle: fallbackToggle,
7878- },
7979- }),
8080- true,
8181- ),
8282- info: {
8383- name,
8484- description,
8585- },
8686- };
8787-8888- if (settings) {
8989- plugin.settings = settings;
9090- }
9191-9292- return plugin;
9393-}
9494-9595-export const plugins: Record<Types.PluginId, Types.PluginData> = {
9696- subheader: createPlugin(
9797- "subheader",
9898- "Subheader Revamp",
9999- "Adds a clock and current period info to the subheader.",
100100- true,
101101- {
102102- toggle: {
103103- openInNewTab: {
104104- toggle: new StorageState(
105105- storage.defineItem<Types.ToggleSetting>("local:plugin-subheaderRevamp-openInNewTab", {
106106- fallback: {
107107- toggle: true,
108108- },
109109- }),
110110- ),
111111- info: {
112112- name: "Open links in new tab",
113113- description: "Whether to open the class link in a new tab."
114114- }
115115- },
116116- },
117117- },
118118- ),
119119-120120- scrollSegments: createPlugin(
121121- "scrollSegments",
122122- "Scroll Segments",
123123- "Segments the Schoolbox page into scrollable sections.",
124124- true,
125125- ),
126126-127127- scrollPeriod: createPlugin("scrollPeriod", "Scroll Period", "Scrolls to the current period on the timetable.", true, {
128128- toggle: {
129129- resetCooldownOnMouseMove: {
130130- toggle: new StorageState(
131131- storage.defineItem<Types.ToggleSetting>("local:plugin-scrollPeriod-resetCooldownOnMouseMove", {
132132- fallback: {
133133- toggle: true,
134134- },
135135- }),
136136- ),
137137- info: {
138138- name: "Reset on mouse move",
139139- description: "Whether to reset the scrolling cooldown when you move your mouse.",
140140- },
141141- },
142142- },
143143- slider: {
144144- cooldownDuration: {
145145- slider: new StorageState(
146146- storage.defineItem<Types.SliderSetting>("local:plugin-scrollPeriod-cooldownDuration", {
147147- fallback: {
148148- min: 1,
149149- max: 60,
150150- value: 10,
151151- },
152152- }),
153153- ),
154154- info: {
155155- name: "Cooldown duration (s)",
156156- description: "How long to wait before scrolling.",
157157- },
158158- },
159159- },
160160- }),
161161-162162- progressBar: createPlugin(
163163- "progressBar",
164164- "Progress Bar",
165165- "Displays a progress bar below the timetable to show the time of the day.",
166166- true,
167167- ),
168168-169169- modernIcons: createPlugin("modernIcons", "Modern Icons", "Modernise the icons across Schoolbox.", true, {
170170- toggle: {
171171- filled: {
172172- toggle: new StorageState(
173173- storage.defineItem<Types.ToggleSetting>("local:plugin-modernIcons-filled", {
174174- fallback: {
175175- toggle: true,
176176- },
177177- }),
178178- ),
179179- info: {
180180- name: "Filled Icons",
181181- description: "Whether the icons should be filled or outlined.",
182182- },
183183- },
184184- },
185185- }),
186186-187187- tabTitle: createPlugin("tabTitle", "Better Tab Titles", "Improves the tab titles for easier navigation.", true, {
188188- toggle: {
189189- showSubjectPrefix: {
190190- toggle: new StorageState(
191191- storage.defineItem<Types.ToggleSetting>("local:plugin-tabTitle-showSubjectPrefix", {
192192- fallback: {
193193- toggle: true,
194194- },
195195- }),
196196- ),
197197- info: {
198198- name: "Show subject prefix",
199199- description: `e.g. "ENG - VCE English 1 & 2" becomes "VCE English 1 & 2"`,
200200- },
201201- },
202202- },
203203- }),
204204-205205- homepageSwitcher: createPlugin(
206206- "homepageSwitcher",
207207- "Homepage Switcher",
208208- "The logo will switch to existing Schoolbox homepage when available.",
209209- true,
210210- {
211211- toggle: {
212212- closeCurrentTab: {
213213- toggle: new StorageState(
214214- storage.defineItem<Types.ToggleSetting>("local:plugin-homepageSwitcher-closeCurrentTab", {
215215- fallback: {
216216- toggle: false,
217217- },
218218- }),
219219- ),
220220- info: {
221221- name: "Close current tab",
222222- description: "When switching to another tab, close the current one.",
223223- },
224224- },
225225- },
226226- },
227227- ),
228228-};
229229-230230-// Snippets
231231-function createSnippet(id: string, name: string, description: string, fallbackToggle: boolean) {
232232- return {
233233- toggle: new StorageState(
234234- storage.defineItem<Types.ItemGeneric>(`local:snippet-${id}`, {
235235- fallback: {
236236- toggle: fallbackToggle,
237237- },
238238- }),
239239- true,
240240- ),
241241- info: {
242242- name,
243243- description,
244244- },
245245- };
246246-}
247247-248248-export const snippets: Record<Types.SnippetId, Types.SnippetData> = {
249249- roundedCorners: createSnippet(
250250- "roundedCorners",
251251- "Rounded Corners",
252252- "Adds rounded corners to all elements across Schoolbox.",
253253- true,
254254- ),
255255-256256- hidePfp: createSnippet("hidePfp", "Hide PFP", "Hide your profile picture across Schoolbox.", true),
257257-258258- hidePwaPrompt: createSnippet(
259259- "hidePwaPrompt",
260260- "Hide PWA Prompt",
261261- "Hides the prompt in the notifications menu to install Schoolbox as a PWA and enable notifications.",
262262- true,
263263- ),
264264-265265- censor: createSnippet(
266266- "censor",
267267- "Censor",
268268- "Censors all text and images. This is intended for development purposes.",
269269- false,
270270- ),
271271-};