Rewild Your Web
web
browser
dweb
1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3const THEME_PREF_KEY = "browserhtml.theme";
4const DEFAULT_THEME = "default";
5
6// Available themes - TODO: make that dynamic
7const AVAILABLE_THEMES = [
8 { id: "default", name: "Default", description: "Vibrant gradient theme" },
9 { id: "lcars", name: "LCARS", description: "Star Trek sci-fi aesthetic" },
10 { id: "meadow", name: "Meadow", description: "Peaceful nature-inspired" },
11 { id: "winamp", name: "Winamp", description: "Classic media player vibes" },
12];
13
14/**
15 * Get the list of available themes
16 * @returns {Array<{id: string, name: string, description: string}>}
17 */
18export function getAvailableThemes() {
19 return AVAILABLE_THEMES;
20}
21
22/**
23 * Get the currently selected theme ID from preferences
24 * @returns {string} Theme ID
25 */
26export function getTheme() {
27 try {
28 // Use navigator.servo preference API if available
29 if (navigator.servo) {
30 const theme = navigator.servo.getStringPreference(THEME_PREF_KEY);
31 if (theme && theme !== "") {
32 return theme;
33 }
34 }
35 } catch (e) {
36 // Preference not set or API not available
37 }
38 return DEFAULT_THEME;
39}
40
41/**
42 * Set the theme and persist to preferences
43 * @param {string} themeId - The theme ID to set
44 */
45export function setTheme(themeId) {
46 // Validate theme exists
47 const theme = AVAILABLE_THEMES.find((t) => t.id === themeId);
48 if (!theme) {
49 console.warn(`Theme "${themeId}" not found, using default`);
50 themeId = DEFAULT_THEME;
51 }
52
53 // Persist to preferences via navigator.servo API
54 // This will trigger preferencechanged event on navigator.embedder
55 try {
56 if (navigator.servo) {
57 navigator.servo.setStringPreference(THEME_PREF_KEY, themeId);
58 }
59 } catch (e) {
60 console.warn("Could not save theme preference:", e);
61 }
62}
63
64/**
65 * Apply the current theme by updating the theme stylesheet link
66 */
67function applyTheme() {
68 const themeLink = document.querySelector('link[href*="theme.localhost"]');
69 if (themeLink) {
70 themeLink.href = `http://theme.localhost:8888/index.css?${Math.round(Math.random() * 1000000)}`;
71 } else {
72 console.error(`Failed to apply theme on ${location.href}`);
73 }
74}
75
76/**
77 * Initialize theme system - call this on page load
78 * Sets up the current theme and listens for preference changes
79 */
80function initTheme() {
81 // Listen for preference changes from the embedder
82 if (navigator.embedder) {
83 navigator.embedder.addEventListener("preferencechanged", (event) => {
84 console.log(`[Theme PrefChanged-${location.href}] ${event.detail.name} : ${event.detail.value}`);
85 if (event.detail.name === THEME_PREF_KEY) {
86 applyTheme();
87 }
88 });
89 }
90}
91
92initTheme();