work on settings and spell checker UI/UX
authorRaphaël Jakse <raphael.trivabble@jakse.fr>
Sat, 29 Aug 2020 10:26:05 +0000 (12:26 +0200)
committerRaphaël Jakse <raphael.trivabble@jakse.fr>
Sat, 29 Aug 2020 10:26:05 +0000 (12:26 +0200)
l10n/po/fr/trivabble.po
l10n/pot/trivabble.pot
public/config.js.sample
public/index.html
public/trivabble.css
public/trivabble.js
server/trivabble-server.js

index 8e4292f010c94c3d9c0f9e0d1506b225e6f5fb58..752e8bb3ce0ac8b8d433c95f4e115c96adcf4c29 100644 (file)
@@ -187,11 +187,11 @@ msgstr "Impossible de charger le dictionnaire"
 msgid  "Enable spell checker"
 msgstr "Activer le vérificateur orthographique"
 
-msgid  "Spell checking requires Trivabble to download a dictionary. This dictionary is based on Aspell. Do you confirm?"
-msgstr "La vérification orthographique nécessite que Trivabble télécharge un dictionnaire. Ce dictionnaire est construit grâce à Aspell. Confirmez-vous ?"
+msgid  "Spell checking requires Trivabble to download a dictionary. Do you confirm?"
+msgstr "La vérification orthographique nécessite que Trivabble télécharge un dictionnaire. Confirmez-vous ?"
 
-msgid  "Configuration"
-msgstr "Options de configuration"
+msgid  "Spell checking is based on:"
+msgstr "La vérification orthographique est basée sur :"
 
-msgid  "Configuration window"
-msgstr "Fenêtre de configuration"
+msgid  "Settings"
+msgstr "Paramètres"
\ No newline at end of file
index 7d954283c50fc4ff032ab518827d80de0ca8ec75..e8300029947387ecbf87b95fc9d13bd8744c39e5 100644 (file)
@@ -193,11 +193,11 @@ msgstr ""
 msgid  "Enable spell checker"
 msgstr ""
 
-msgid  "Spell checking requires Trivabble to download a dictionary. This dictionary is based on Aspell. Do you confirm?"
+msgid  "Spell checking requires Trivabble to download a dictionary. Do you confirm?"
 msgstr ""
 
-msgid  "Configuration"
+msgid  "Spell checking is based on:"
 msgstr ""
 
-msgid  "Configuration window"
-msgstr ""
+msgid  "Settings"
+msgstr ""
\ No newline at end of file
index 2a69af54d4d8ee5bd991065d40970f4edebebce2..bdd78458fa395dcfac06341be6cf4fc337fd8ddd 100644 (file)
@@ -17,8 +17,8 @@ window.TrivabbleConf = {
     // to tweak only if your webserver is shared with other conflicting resources at / ( ex: yunohost integration )
     APP_PATH: "",
 
-    // Whether Check spelling is enabled (dictionaries must be downloaded on the server before enabling this option
-    ENABLE_CHECK_SPELLING: false,
+    // Whether the spell checker is enabled (dictionaries must be downloaded on the server before enabling this option)
+    ENABLE_SPELL_CHECKER: false,
 
     // I don't like trailing commas, here is a nice message for you reading this file :-)
     HAVE_FUN: true
index be8dd23787aba7082446a19be22da9042a6f66de..a8096464bdce8a5f492c3b849f366c087e4e6f28 100644 (file)
             </div>
         </div>
 
-        <div class="modal" id="modal-config-dialog">
+        <div class="modal" id="modal-settings-dialog">
             <div class="modal-content">
                 <h2>
-                    <span data-l10n="text-content">Configuration window</span>
-                    <span class="modal-button" id="modal-close-btn">&#215;</span>
-               </h2>
+                    <span data-l10n="text-content">Settings</span>
+                    <span class="modal-button" id="btn-settings-close">&#215;</span>
+                       </h2>
                 <div id="prefs-sound">
                     <p><label><input type="checkbox" id="tiles-sound" checked="checked" /><span data-l10n="text-content">Sound of the tiles</span></label></p>
                     <p><label><input type="checkbox" id="msg-sound" checked="checked" /><span data-l10n="text-content">Sound of messages</span></label></p>
-                    <p><label><input type="checkbox" id="enable-spell-checker" style="display:none" /> <span data-l10n="text-content">Enable spell checker</span></label></p>
+                    <p id="enable-spell-checker-outer" style="display:none"><label><input type="checkbox" id="enable-spell-checker" /> <span data-l10n="text-content">Enable spell checker</span></label></p>
                 </div>
             </div>
         </div>
-        
+
        <div id="content">
             <table id="board">
                 <tr><td class="corner"></td></tr>
@@ -68,6 +68,7 @@
         </div>
 
         <div id="panel">
+            <button id="btn-settings" data-l10n="text-content">Settings</button>
             <div id="bag"></div>
             <p><span data-l10n="text-content">Number of tiles in the bag:</span><br /><span id="remaining-letters">102</span><br /><span id="help-bag" data-l10n="text-content">Click on it to take one.</span><a href="#" id="help-clear" style="display:none"></a></p>
             <table id="participants">
@@ -78,8 +79,8 @@
             <p id="help-turn" data-l10n="text-content">Who's turn? Click on the Turn button!</p>
             <button id="clear-rack" class="minibutton" data-l10n="text-content">Put back all the tiles of&#10;your rack in the bag</button>
             <button id="show-rack" class="minibutton" data-l10n="text-content">Show my rack to other players</button>
-            <button id="check-spelling" class="minibutton" data-l10n="text-content" style="display: none">Check spelling for new words</button>
-            <button id="modal-config-btn" class="text-content" data-l10n="text-content">Configuration</button>
+            <button id="check-spelling" class="minibutton" data-l10n="text-content" style="display:none">Check spelling for new words</button>
+            <p id="info-spell-checking" style="display:none;"><span data-l0n="text-content">Spell checking is based on:</span> <a rel="noopener noreferrer" target="_blank" href="http://aspell.net">Aspell</a></p>
         </div>
     </body>
 </html>
index da4138a52d72f416d169dfd3ef76d0552a536a72..50ab0eed405824dd2eb42ec42dcc8ef8a5d61c1d 100644 (file)
@@ -356,7 +356,8 @@ td.blink {
     width:165px;
     height:160px;
     background:url(bag.svg) no-repeat;
-    background-size:100% 100%
+    background-size:100% 100%;
+    flex:1;
 }
 
 #bag:hover {
@@ -511,9 +512,11 @@ td.blink {
     border-radius: 0.25rem;
     background-color: lightgray;
 }
-.modal-button:hover {
+
+.modal-button:hover, #btn-settings:hover {
     background-color: darkgray;
 }
+
 .show-modal {
     opacity: 1;
     visibility: visible;
@@ -524,3 +527,26 @@ td.blink {
 .alert {
     z-index: 2;
 }
+
+#btn-settings {
+    background:lightgray;
+    color:black;
+    font-size:small;
+    border-radius:3px;
+    border:none;
+    margin:0 0 0 auto;
+    min-height: 2em;
+}
+
+#btn-settings:before {
+    content: "⚙️ "
+}
+
+#info-spell-checking {
+    font-size:small;
+    color:gray;
+}
+
+#info-spell-checking a {
+    color:black;
+}
\ No newline at end of file
index bb50e36adef9abddb0556ec6729e0aca2030eb27..aa525183d655dcf7e3f80451e0390bdd10f67738 100644 (file)
@@ -60,7 +60,7 @@
     let scoreOf;
     let bag;
     let boardLangSelect;
-    let dictionary;
+    const downloadedDictionaries = {};
 
     const playerLetters = [];
     let currentPlayer = "";
         }
     }
 
-    function setSpellCheckerState(enabled) {
-        if (enabled !== null) {
-            localStorage.spellCheckerEnabled = enabled.toString();
-        }
+    function getDictionary(code, callback, force) {
+        if (downloadedDictionaries[code]) {
+            if (downloadedDictionaries[code].length) {
+                if (callback) {
+                    callback(downloadedDictionaries[code]);
+                    return;
+                }
+            }
 
-        if (localStorage.spellCheckerEnabled === "false") {
-            document.getElementById("enable-spell-checker").checked = false;
-            document.getElementById("check-spelling").style.display = "none";
-        } else {
-            document.getElementById("enable-spell-checker").checked = true;
-            document.getElementById("check-spelling").style.display = "";
+            // FIXME we silently never call the callback here
+            return;
         }
-    }
 
-    function downloadDictionary(code) {
-        if (localStorage.spellCheckerEnabled === code) {
+        if (!force && localStorage.spellCheckerEnabled !== "true") {
+            myConfirm(
+                _("Spell checking requires Trivabble to download a dictionary. Do you confirm?"),
+                function () {
+                    localStorage.spellCheckerEnabled = "true";
+                    getDictionary(code, callback, true);
+                }
+            );
             return;
         }
 
+        // Avoid redownloading the dictionary if a download is on its way
+        downloadedDictionaries[code] = [];
+
         const file = new XMLHttpRequest();
-        file.overrideMimeType("application/dictionary");
         file.open("GET", "dict/" + code + ".dict", true);
         file.onreadystatechange = function () {
             if (file.readyState === 4) {
                 if (file.status === 200) {
                     try {
-                        dictionary = file.responseText.split("\n");
-                        setSpellCheckerState(code);
+                        const dictionary = file.responseText.split("\n");
+                        downloadedDictionaries[code] = dictionary;
+                        callback(dictionary);
+                        return;
                     } catch (e) {
+                        delete downloadedDictionaries[code];
                         myAlert(_("Incorrect dictionary file."));
-                        setSpellCheckerState(false);
                     }
                 } else {
+                    delete downloadedDictionaries[code];
                     myAlert(_("Can't load dictionary file."));
-                    setSpellCheckerState(false);
                 }
             }
         };
-        file.send(null);
+        file.send();
     }
 
-    function enableSpellChecker() {
-        if (document.getElementById("enable-spell-checker").checked) {
-            myConfirm(
-                _("Spell checking requires Trivabble to download a dictionary. This dictionary is based on Aspell. Do you confirm?"),
-                function () {
-                    downloadDictionary(localStorage.trivabbleBoardLang);
-                },
-                function () {
-                    setSpellCheckerState(false);
-                });
-        } else {
-            setSpellCheckerState(false);
-        }
+    function spellCheckerSettingChecked() {
+        localStorage.spellCheckerEnabled = document.getElementById("enable-spell-checker").checked.toString();
+        initSpellChecker();
     }
 
     function removeElem(elem) {
             case "boardLang":
                 localStorage.trivabbleBoardLang = value;
                 document.getElementById("board-lang").value = value;
-                if (localStorage.spellCheckerEnabled !== "false") {
-                    downloadDictionary(value);
-                }
                 break;
         }
     }
         }
     }
 
-    function checkSpelling() {
+    function checkSpellingClicked() {
         if (localStorage.spellCheckerEnabled === "false") {
             return;
         }
 
+        getDictionary(localStorage.trivabbleBoardLang, checkSpelling);
+    }
+
+    function checkSpelling(dictionary) {
         const newWords = searchNewWords();
         if (newWords.length === 0) {
             myAlert(_("No new word found"));
     }
 
     function initSpellChecker() {
-        if (!localStorage.spellCheckerEnabled) {
-            localStorage.spellCheckerEnabled = Conf.ENABLE_SPELL_CHECKER.toString();
+        if (Conf.ENABLE_SPELL_CHECKER) {
+            document.getElementById("enable-spell-checker-outer").style.display = "";
         }
 
-        document.getElementById("enable-spell-checker").onclick = enableSpellChecker;
+        document.getElementById("enable-spell-checker").onclick = spellCheckerSettingChecked;
 
-        if (localStorage.spellCheckerEnabled === "false") {
-            setSpellCheckerState(false);
+        if (!Conf.ENABLE_SPELL_CHECKER || localStorage.spellCheckerEnabled === "false") {
+            document.getElementById("check-spelling").style.display = "none";
+            document.getElementById("enable-spell-checker").checked = false;
+            document.getElementById("info-spell-checking").style.display = "none";
         } else {
-            const spellChecker = localStorage.spellCheckerEnabled;
-            localStorage.spellCheckerEnabled = "false";
-            downloadDictionary(spellChecker);
+            document.getElementById("check-spelling").style.display = "";
+            document.getElementById("info-spell-checking").style.display = "";
+            document.getElementById("enable-spell-checker").checked = true;
         }
     }
 
         location.reload();
     }
 
-    function showConfig() {
+    function showSettings() {
        const modal = document.querySelector(".modal");
        modal.classList.toggle("show-modal");
     }
         document.getElementById("join-game").onclick   = joinGame;
         document.getElementById("clear-rack").onclick  = clearRack;
         document.getElementById("show-rack").onclick   = showRack;
-        document.getElementById("check-spelling").onclick = checkSpelling;
+        document.getElementById("check-spelling").onclick = checkSpellingClicked;
         helpClear.onclick  = clearGame;
 
-       document.getElementById("modal-config-btn").onclick = showConfig;
-       document.getElementById("modal-close-btn").onclick = showConfig;
+        document.getElementById("btn-settings").onclick = showSettings;
+        document.getElementById("btn-settings-close").onclick = showSettings;
     }
 
     function initGame() {
index 07bc61446cb423356e53c64f8b6f81d858bcb23d..7421b2523775525e28599299532e3c06cff4e467 100644 (file)
@@ -980,7 +980,8 @@ function handleRequest(request, response) {
                             ".ogg": "audio/ogg",
                             ".js": "application/javascript; charset=utf-8",
                             ".css": "text/css; charset=utf-8",
-                            ".svg": "image/svg+xml"
+                            ".svg": "image/svg+xml",
+                            ".dict": "text/plain"
                         };
 
                         for (const i in mimes) {