#21: add a color theme switch
authorRaphaël Jakse <raphael.trivabble@jakse.fr>
Sun, 3 Aug 2025 12:09:02 +0000 (14:09 +0200)
committerRaphaël Jakse <raphael.trivabble@jakse.fr>
Sun, 3 Aug 2025 12:16:13 +0000 (14:16 +0200)
l10n/po/fr/trivabble.po
l10n/pot/trivabble.pot
public/index.html
public/trivabble.js

index 61537e18fc667165c2356fc25ce0a9fcd93dd685..9ee37fea8df1d6c9e877e54f5db79895dfc2afca 100644 (file)
@@ -256,6 +256,18 @@ msgstr "{0} h {1} min {2} s"
 msgid  "{0}' {1}''"
 msgstr "{0} min {1}"
 
+msgid  "Theme:"
+msgstr "Thème :"
+
+msgid "Auto"
+msgstr "Automatique"
+
+msgid  "Dark"
+msgstr "Sombre"
+
+msgid  "Light"
+msgstr "Clair"
+
 msgid  "Show the timer"
 msgstr "Chronométrer la partie"
 
index 4dd5c9ffcaf9d14717adb117bdd67806bd7e0ae4..7198382da38629db37ea059f688bc9ac8157d831 100644 (file)
@@ -262,6 +262,18 @@ msgstr ""
 msgid  "{0}' {1}''"
 msgstr ""
 
+msgid  "Theme:"
+msgstr ""
+
+msgid "Auto"
+msgstr ""
+
+msgid  "Dark"
+msgstr ""
+
+msgid  "Light"
+msgstr ""
+
 msgid  "Show the timer"
 msgstr ""
 
index 7b98c1ca37cd135bbca5d745fe382672000a2ec2..921aae18e2d4c56d8385e83da2ac8db364d8ac9a 100644 (file)
                     <h1 data-l10n="text-content">Settings</h1>
                     <button class="modal-button" id="btn-settings-close">&#215;</button>
                 </div>
+                <div>
+                    <p><label><span data-l10n="text-content">Theme:</span> <select id="theme">
+                        <option value="" data-l10n="text-content">Auto</option>
+                        <option value="dark" data-l10n="text-content">Dark</option>
+                        <option value="light" data-l10n="text-content">Light</option>
+                    </select></label></p>
+                </div>
                 <div>
                     <p><label><input type="checkbox" id="enable-timer" /> <span data-l10n="text-content">Show the timer</span></label></p>
                        </div>
index 105f88936451c94f6ce6981fa59b36adab8b0619..bb305ad883dc038cc8b164ef45a10d24a900b365 100644 (file)
         GameNumber: "number",
         BoardLabel: "string",
         Lang: "string",
+        Theme: "string",
         PlayerName: "string",
         CheckFirstWord: "number",
         FreezePlayedTiles: "number",
             }
         );
     }
-    
+
+    function onChangeTheme() {
+        console.log(document.getElementById("theme").value);
+        setSetting("Theme", document.getElementById("theme").value);
+        handleTheme();
+    }
+
     function onChangeBoardLabel() {
         const label = document.getElementById("board-label").value;
 
         document.getElementById("next-help-msg").onclick = nextHelpMessage;
         document.getElementById("disable-spell-checker").onclick = toggleSpellChecker;
         document.getElementById("score-words").onclick = scoreWords;
+        document.getElementById("theme").onchange = onChangeTheme;
         window.addEventListener("keydown", function (e) {
             if (e.key === "Escape") {
                 document.querySelector(".modal").classList.remove("show-modal");
             document.getElementById("board-label").value = getSetting("BoardLabel");
         }
 
+        document.getElementById("theme").value = getSetting("Theme", "");
+
         startGame(getSetting("GameNumber"));
     }
 
         content.style.zoom = candidateScale;
     }
 
+    // thanks https://mybyways.com/blog/forcing-dark-mode-with-prefs-color-scheme-media-query
+    function setPreferredColorScheme(mode) {
+        console.log("SETPREFERREDCOLORSCHEME", mode);
+        const rules = document.styleSheets[0].rules;
+        const len = rules.length;
+        for (var i = len - 1; i >= 0; i--) {
+            const rule = rules[i].media;
+            if (rule.mediaText.includes("prefers-color-scheme")) {
+                switch (mode) {
+                    case "light":
+                        rule.appendMedium("original-prefers-color-scheme");
+                        if (rule.mediaText.includes("light")) {
+                            rule.deleteMedium("(prefers-color-scheme: light)");
+                        }
+                        if (rule.mediaText.includes("dark")) {
+                            rule.deleteMedium("(prefers-color-scheme: dark)");
+                        }
+                        break;
+                    case "dark":
+                        rule.appendMedium("(prefers-color-scheme: light)");
+                        rule.appendMedium("(prefers-color-scheme: dark)");
+                        if (rule.mediaText.includes("original")) {
+                            rule.deleteMedium("original-prefers-color-scheme");
+                        }
+                        break;
+                    default:
+                        rule.appendMedium("(prefers-color-scheme: dark)");
+                        if (rule.mediaText.includes("light")) {
+                            rule.deleteMedium("(prefers-color-scheme: light)");
+                        }
+                        if (rule.mediaText.includes("original")) {
+                            rule.deleteMedium("original-prefers-color-scheme");
+                        }
+                    }
+                break;
+            }
+        }
+    }
+
+    function handleTheme() {
+        setPreferredColorScheme(getSetting("Theme", ""));
+    }
+
+    function initTheme() {
+        window.matchMedia('(prefers-color-scheme: dark)').addListener(handleTheme);
+        handleTheme();
+    }
+
     function load() {
+        initTheme();
         initLang();
         loadBagSVG();
     }