From d51816bf7af7fb5442e4d313721df9e06bfd5af1 Mon Sep 17 00:00:00 2001 From: skid-dev <62094231+skid-dev@users.noreply.github.com> Date: Thu, 2 Apr 2026 09:46:57 +1100 Subject: [PATCH 1/2] fix (launcher): Update launcher script reference --- src/background/events/injects/launcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/background/events/injects/launcher.ts b/src/background/events/injects/launcher.ts index 3c93e59..042cf50 100644 --- a/src/background/events/injects/launcher.ts +++ b/src/background/events/injects/launcher.ts @@ -10,7 +10,7 @@ export default { action: async (base, settings) => { await chrome.scripting.executeScript({ target: { tabId: base.tab_id }, - files: ["content.js"], + files: ["launcher_homepage.js"], }) await chrome.scripting.insertCSS({ target: { tabId: base.tab_id }, From a54a64aac72c916bcb1851747d82a2d14bcdd7f6 Mon Sep 17 00:00:00 2001 From: skid-dev <62094231+skid-dev@users.noreply.github.com> Date: Thu, 2 Apr 2026 10:03:59 +1100 Subject: [PATCH 2/2] feat: auto-detection for light/dark schooltape themes --- .../modules/launcher/detect_dark_theme.ts | 54 +++++++++++++++++++ .../modules/launcher/display_results.ts | 4 +- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/content/modules/launcher/detect_dark_theme.ts diff --git a/src/content/modules/launcher/detect_dark_theme.ts b/src/content/modules/launcher/detect_dark_theme.ts new file mode 100644 index 0000000..135c40f --- /dev/null +++ b/src/content/modules/launcher/detect_dark_theme.ts @@ -0,0 +1,54 @@ +export function rgb_to_hex(rgb: string): string { + const m = rgb.match(/rgba?\(\s*([\d.]+%?)\s*,\s*([\d.]+%?)\s*,\s*([\d.]+%?)(?:\s*,\s*[\d.]+\s*)?\)/i) + if (!m) { + throw new Error("Invalid RGB color format. Expected 'rgb(...)' or 'rgba(...)'.") + } + + const parseChannel = (v: string) => { + if (v.endsWith("%")) { + return Math.round((parseFloat(v) / 100) * 255) + } + return Math.round(parseFloat(v)) + } + + const r = parseChannel(m[1]) + const g = parseChannel(m[2]) + const b = parseChannel(m[3]) + + const toHex = (v: number) => v.toString(16).padStart(2, "0") + return `#${toHex(r)}${toHex(g)}${toHex(b)}` +} + +/** + * Determines if a background color is "light" or "dark". + * Useful for deciding whether to use black or white text over a dynamic background. + * * @param hexColor - The background color in hex format (e.g., "#FFFFFF", "FFF", "123456") + * @returns 'light' (suggesting dark text) or 'dark' (suggesting light text). + */ +export function get_theme(hexColor: string): "light" | "dark" { + // 1. Strip the leading hash if it exists + const hex = hexColor.replace(/^#/, "") + + // 2. Parse the hex string into RGB integer values + let r: number, g: number, b: number + + if (hex.length === 3) { + // Handle 3-character hex (e.g., #FFF -> #FFFFFF) + r = parseInt(hex[0] + hex[0], 16) + g = parseInt(hex[1] + hex[1], 16) + b = parseInt(hex[2] + hex[2], 16) + } else if (hex.length === 6) { + // Handle standard 6-character hex + r = parseInt(hex.substring(0, 2), 16) + g = parseInt(hex.substring(2, 4), 16) + b = parseInt(hex.substring(4, 6), 16) + } else { + throw new Error("Invalid hex color format. Please provide a 3 or 6 character hex string.") + } + + // 3. Calculate perceived brightness using the YIQ formula + const yiq = (r * 299 + g * 587 + b * 114) / 1000 + + // 4. Return the theme based on the 128 midpoint threshold + return yiq >= 128 ? "light" : "dark" +} diff --git a/src/content/modules/launcher/display_results.ts b/src/content/modules/launcher/display_results.ts index b11edde..312e1f4 100644 --- a/src/content/modules/launcher/display_results.ts +++ b/src/content/modules/launcher/display_results.ts @@ -4,6 +4,7 @@ import { lighten } from "../../functions/lighten" import { darken } from "../../functions/darken" import { Settings } from "../../../types/settings" import { check_in_schoolbox_domain } from "../../../background/functions/utls/is_page" +import { get_theme, rgb_to_hex } from "./detect_dark_theme" export interface LauncherSearchResult { item: IndexedItem @@ -102,7 +103,8 @@ export async function display_results( const is_schoolbox_domain = await check_in_schoolbox_domain(window.location.href) const is_dark_mode = stored_settings?.inject_css || - (stored_settings?.schooltape_compatibility && is_schoolbox_domain) + (is_schoolbox_domain && + get_theme(rgb_to_hex(getComputedStyle(document.body).backgroundColor)) === "dark") parent_div.innerHTML = "" for (let result of results) {