Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/improsocial/impro
An extensible Bluesky client for web impro.social
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225import { Capacitor, StatusBar } from "/js/lib/capacitor.js";import { Signal } from "/js/signals.js";
function getRootStyle() { return getComputedStyle(document.documentElement);}
function resolveCssColor(value) { const probe = document.createElement("div"); probe.style.color = value; probe.style.display = "none"; document.documentElement.appendChild(probe); const resolved = getComputedStyle(probe).color; probe.remove(); return resolved;}
export function getDefaultHighlightColor() { return getRootStyle().getPropertyValue("--blue");}
export function getDefaultLikeColor() { return getRootStyle().getPropertyValue("--pink");}
export function getDefaultRepostColor() { return getRootStyle().getPropertyValue("--green");}
export function getDefaultColorScheme() { return "system";}
export class Theme { constructor({ highlightColor, likeColor, repostColor, colorScheme }) { this.$highlightColor = new Signal.State(highlightColor); this.$likeColor = new Signal.State(likeColor); this.$repostColor = new Signal.State(repostColor); this.$colorScheme = new Signal.State(colorScheme); }
getBackgroundColor() { return resolveCssColor("var(--background-color)"); }
updateHighlightColor(highlightColor) { this.$highlightColor.set(highlightColor); this.apply(); this.save(); }
updateLikeColor(likeColor) { this.$likeColor.set(likeColor); this.apply(); this.save(); }
updateRepostColor(repostColor) { this.$repostColor.set(repostColor); this.apply(); this.save(); }
updateColorScheme(colorScheme) { this.$colorScheme.set(colorScheme); this.apply(); this.save(); }
apply() { const highlightColor = this.$highlightColor.get(); const likeColor = this.$likeColor.get(); const repostColor = this.$repostColor.get(); const colorScheme = this.$colorScheme.get(); document.documentElement.style.setProperty( `--highlight-color`, highlightColor, ); document.documentElement.style.setProperty(`--like-color`, likeColor); document.documentElement.style.setProperty(`--repost-color`, repostColor); // Apply color scheme if (colorScheme === "system") { document.documentElement.style.setProperty("color-scheme", "light dark"); } else { document.documentElement.style.setProperty("color-scheme", colorScheme); } // Background color for iOS const backgroundColor = this.getBackgroundColor(); let metaThemeColor = document.querySelector("meta[name='theme-color']"); if (!metaThemeColor) { metaThemeColor = document.createElement("meta"); metaThemeColor.name = "theme-color"; document.head.appendChild(metaThemeColor); } metaThemeColor.content = backgroundColor; // Status bar color for iOS native if (Capacitor.isNativePlatform()) { StatusBar.setBackgroundColor({ color: backgroundColor }); } }
save() { const highlightColor = this.$highlightColor.get(); const likeColor = this.$likeColor.get(); const repostColor = this.$repostColor.get(); const colorScheme = this.$colorScheme.get(); if (highlightColor === getDefaultHighlightColor()) { localStorage.removeItem("theme-highlightColorv2"); } else { localStorage.setItem("theme-highlightColorv2", highlightColor); } if (likeColor === getDefaultLikeColor()) { localStorage.removeItem("theme-likeColor"); } else { localStorage.setItem("theme-likeColor", likeColor); } if (repostColor === getDefaultRepostColor()) { localStorage.removeItem("theme-repostColor"); } else { localStorage.setItem("theme-repostColor", repostColor); } if (colorScheme === getDefaultColorScheme()) { localStorage.removeItem("theme-colorScheme"); } else { localStorage.setItem("theme-colorScheme", colorScheme); } }
static fromLocalStorage() { const highlightColor = localStorage.getItem("theme-highlightColorv2") || getDefaultHighlightColor(); const likeColor = localStorage.getItem("theme-likeColor") || getDefaultLikeColor(); const repostColor = localStorage.getItem("theme-repostColor") || getDefaultRepostColor(); const colorScheme = localStorage.getItem("theme-colorScheme") || getDefaultColorScheme(); return new Theme({ highlightColor, likeColor, repostColor, colorScheme }); }}
export const theme = Theme.fromLocalStorage();
const FALLBACK_FONT_STACK = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
export const DEV_FONT_OPTIONS = [ { id: "geist", label: "Geist (default)", family: "Geist" }, { id: "system", label: "System", family: null }, { id: "helvetica", label: "Helvetica / Arial", family: null, stack: '"Helvetica Neue", Helvetica, Arial, sans-serif', }, { id: "ibm-plex-sans", label: "IBM Plex Sans", family: "IBM Plex Sans", weights: "400..700", }, { id: "source-sans-3", label: "Source Sans 3", family: "Source Sans 3" }, { id: "public-sans", label: "Public Sans", family: "Public Sans" }, { id: "libre-franklin", label: "Libre Franklin", family: "Libre Franklin" }, { id: "instrument-sans", label: "Instrument Sans", family: "Instrument Sans", weights: "400..700", }, { id: "hanken-grotesk", label: "Hanken Grotesk", family: "Hanken Grotesk" }, { id: "schibsted-grotesk", label: "Schibsted Grotesk", family: "Schibsted Grotesk", }, { id: "mona-sans", label: "Mona Sans", family: "Mona Sans" }, { id: "figtree", label: "Figtree", family: "Figtree" }, { id: "dm-sans", label: "DM Sans", family: "DM Sans" }, { id: "onest", label: "Onest", family: "Onest" }, { id: "atkinson-hyperlegible-next", label: "Atkinson Hyperlegible Next", family: "Atkinson Hyperlegible Next", },];
const DEV_FONT_STORAGE_KEY = "dev-font";
export function getDevFont() { return localStorage.getItem(DEV_FONT_STORAGE_KEY) || DEV_FONT_OPTIONS[0].id;}
export function setDevFont(fontId) { if (fontId === DEV_FONT_OPTIONS[0].id) { localStorage.removeItem(DEV_FONT_STORAGE_KEY); } else { localStorage.setItem(DEV_FONT_STORAGE_KEY, fontId); } applyDevFont();}
export function applyDevFont() { const font = DEV_FONT_OPTIONS.find((option) => option.id === getDevFont()) ?? DEV_FONT_OPTIONS[0]; document.getElementById("dev-font-stylesheet")?.remove(); if (font === DEV_FONT_OPTIONS[0]) { document.documentElement.style.removeProperty("font-family"); return; } if (font.family) { const link = document.createElement("link"); link.id = "dev-font-stylesheet"; link.rel = "stylesheet"; link.href = `https://fonts.googleapis.com/css2?family=${encodeURIComponent(font.family)}:wght@${font.weights ?? "400..800"}&display=swap`; document.head.appendChild(link); } const stack = font.family ? `"${font.family}", ${FALLBACK_FONT_STACK}` : (font.stack ?? FALLBACK_FONT_STACK); document.documentElement.style.setProperty("font-family", stack);}