diff --git a/Makefile b/Makefile index cf855d8..1015463 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,8 @@ PORT = 3000 ESLINT?=eslint +TIDY?=tidy + ifeq (, $(shell which $(firstword ${ESLINT}))) ESLINT?=npx eslint endif @@ -34,5 +36,8 @@ public/dict/list.js: eslint: -${ESLINT} **/*.js +tidy: + -${TIDY} -xml -errors -q public/*.html + start-dev-server: lang cd server && make start-dev-server diff --git a/l10n/po/fr/trivabble.po b/l10n/po/fr/trivabble.po index a626f20..22e779c 100644 --- a/l10n/po/fr/trivabble.po +++ b/l10n/po/fr/trivabble.po @@ -262,10 +262,26 @@ msgstr "Chronométrer la partie" msgid "To measure playing time, activate the timer." msgstr "Pour mesurer les temps de jeu, activez le chronomètre." +msgid "Cell captions:" +msgstr "Légendes des cellules :" + +msgid "Clip when overflow" +msgstr "Raccourcies en cas de débordement" + +msgid "Dots when overflow" +msgstr "Pointillés en cas de débordement" + +msgid "No caption" +msgstr "Pas de légende" + +msgid "Short caption" +msgstr "Légendes courtes" + msgid "Board label:" msgstr "Type du plateau" msgid "Are you sure you want to change board to {0}? This will put all the tiles back in the bag and start another game." msgstr "Êtes-vous sûr·e de vouloir de changer le type du plateau à {0} ? Cela remettra toutes les lettres du jeu dans le sac et commencera une nouvelle partie." + msgid "Can't find board '{0}'. Change board or start a new game." msgstr "Impossible de trouver le plateau de type '{0}'. Changez de type de plateau ou démarrez une nouvelle partie." diff --git a/l10n/pot/trivabble.pot b/l10n/pot/trivabble.pot index a2b2f2b..3781b8d 100644 --- a/l10n/pot/trivabble.pot +++ b/l10n/pot/trivabble.pot @@ -267,6 +267,21 @@ msgstr "" msgid "To measure playing time, activate the timer." msgstr "" +msgid "Cell captions:" +msgstr "" + +msgid "Clip when overflow" +msgstr "" + +msgid "Dots when overflow" +msgstr "" + +msgid "No caption" +msgstr "" + +msgid "Short caption" +msgstr "" + msgid "Board label:" msgstr "" diff --git a/public/config.js.sample b/public/config.js.sample index 59619b9..601e503 100644 --- a/public/config.js.sample +++ b/public/config.js.sample @@ -3,46 +3,55 @@ window.TrivabbleConf = { // The amount of time to wait after a connection failure - POLLING_DELAY: 2000, + //POLLING_DELAY: 2000, // Whether WebSockets should be used, if possible - ENABLE_WEBSOCKETS: true, + //ENABLE_WEBSOCKETS: true, // Whether Server Sent Events should be used, if available - ENABLE_EVENT_SOURCE: true, + //ENABLE_EVENT_SOURCE: true, // Max consecutive tries before blacklisting WebSockets for the current session - MAX_WEBSOCKET_ERRORS: 1, + //MAX_WEBSOCKET_ERRORS: 1, // To tweak only if your webserver is shared with other conflicting resources at / (e.g. Yunohost integration) - APP_PATH: "", + //APP_PATH: "", // The API entry point. Default value: APP_PATH + '/:trivabble' - API_ENTRY_POINT: "/:trivabble", + //API_ENTRY_POINT: "/:trivabble", - // The color of the flash light when double clicking on a cell - FLASH_LIGHT_COLOR: "#EE6633", + // Wether sounds should be played when receiving messages + //ENABLE_MSG_SOUND: true, - // The list of durations of the flash light available in the settings box - FLASH_LIGHT_DURATIONS: [800, 1600, 3200], - - // The defaut flash light duration. If not set, the value at the middle of the previous array is used. - FLASH_LIGHT_DURATION: 1600, + // Wether sounds should be played when moving tiles + //ENABLE_TILE_SOUND: true, // The list of durations used to detect a double tap available in the settings box - DOUBLE_TAP_DURATIONS: [650, 1100, 1800, 3000, 5000], + //DOUBLE_TAP_DURATIONS: [650, 1100, 1800, 3000, 5000], // The defaut double tap duration. If not set, the value at the middle of the previous array is used. - DOUBLE_TAP_DURATION: 1800, + //DOUBLE_TAP_DURATION: 1800, + + // The color of the flash light when double clicking on a cell + //FLASH_LIGHT_COLOR: "#EE6633", + + // The list of durations of the flash light available in the settings box + //FLASH_LIGHT_DURATIONS: [800, 1600, 3200], + + // The defaut flash light duration. If not set, the value at the middle of the previous array is used. + //FLASH_LIGHT_DURATION: 1600, // The default premium for playing seven tiles on a turn - PREMIUM_SEVEN_TILES: 50, + //PREMIUM_SEVEN_TILES: 50, // Score is automically affected to last player. If false, score is automatically affected to the player who pressed the Score button - SCORE_LAST_PLAYER: true, + //SCORE_LAST_PLAYER: true, // Timer activation - ENABLE_TIMER: false, + //ENABLE_TIMER: false, + + // Cell captions. Could be "clip", "dots", "none" or "short" + //CELL_CAPTIONS: "dots", // I don't like trailing commas, here is a nice message for you reading this file :-) HAVE_FUN: true diff --git a/public/index.html b/public/index.html index 6ba07e0..ebb2611 100644 --- a/public/index.html +++ b/public/index.html @@ -108,6 +108,19 @@

+
+

+ +

+
diff --git a/public/trivabble.css b/public/trivabble.css index 85127fd..b36d130 100644 --- a/public/trivabble.css +++ b/public/trivabble.css @@ -122,10 +122,25 @@ html, #board, [draggable], .tile { display:inline-block; white-space:pre-wrap; font-size:7px; - text-overflow:ellipsis; overflow:hidden; } +.special-cell-label-clip .special-cell-label { + text-overflow:clip; +} + +.special-cell-label-dots .special-cell-label { + text-overflow:ellipsis; +} + +.special-cell-label-none .special-cell-label { + visibility:hidden; +} + +.special-cell-label-short .special-cell-label { + display:inline; +} + #center-cell .special-cell-label { font-weight:bold; color:black; diff --git a/public/trivabble.js b/public/trivabble.js index 53125e5..93699af 100644 --- a/public/trivabble.js +++ b/public/trivabble.js @@ -54,17 +54,18 @@ setConf("ENABLE_EVENT_SOURCE", true); setConf("MAX_WEBSOCKET_ERRORS", 1); setConf("APP_PATH", ""); + setConf("API_ENTRY_POINT", Conf.APP_PATH + "/:trivabble"); setConf("ENABLE_MSG_SOUND", true); setConf("ENABLE_TILE_SOUND", true); setConf("DOUBLE_TAP_DURATIONS", [650, 1100, 1800, 3000, 5000]); setConf("DOUBLE_TAP_DURATION", middle("DOUBLE_TAP_DURATIONS")); + setConf("FLASH_LIGHT_COLOR", "#ee6633"); setConf("FLASH_LIGHT_DURATIONS", [800, 1600, 3200]); setConf("FLASH_LIGHT_DURATION", middle("FLASH_LIGHT_DURATIONS")); - setConf("FLASH_LIGHT_COLOR", "#ee6633"); - setConf("API_ENTRY_POINT", Conf.APP_PATH + "/:trivabble"); setConf("PREMIUM_SEVEN_TILES", 50); setConf("SCORE_LAST_PLAYER", true); setConf("ENABLE_TIMER", false); + setConf("CELL_CAPTIONS", "dots"); // "clip", "dots", "none", "short" function isSetting(key) { return Object.prototype.hasOwnProperty.call(Conf, key) || @@ -138,7 +139,13 @@ (type === "number") || (type === "object") || (type === "string")) { - localStorage.setItem("trivabble" + key, value); + if (Object.prototype.hasOwnProperty.call(Conf, key) && (Conf[key] === value)) { + if (Object.prototype.hasOwnProperty.call(localStorage, "trivabble" + key)) { + delete localStorage["trivabble" + key]; + } + } else { + localStorage.setItem("trivabble" + key, value); + } } else { console.error("Unsupported type"); } @@ -148,15 +155,14 @@ } const SettingsTypes = { - SpellCheckerEnabledOnce: "boolean", + BoardLang: "string", DisableSpellChecker: "boolean", GameNumber: "number", BoardLang: "string", BoardLabel: "string", Lang: "string", PlayerName: "string", - Timer: "number", - TimerEnable: "boolean", + SpellCheckerEnabledOnce: "boolean", TimerGameDate: "number", TimerTurnDate: "number" }; @@ -1410,7 +1416,7 @@ webSocket = new WebSocket( (window.location.protocol === "http:" ? "ws://" : "wss://") + window.location.host + - Conf.API_ENTRY_POINT + "/ws/" + + getSetting("API_ENTRY_POINT") + "/ws/" + JSON.stringify(cmdsWithContext()) ); @@ -1424,7 +1430,7 @@ function xhrRequest(data, onreadystatechange) { const xhr = new XMLHttpRequest(); - xhr.open("POST", Conf.API_ENTRY_POINT, true); + xhr.open("POST", getSetting("API_ENTRY_POINT"), true); xhr.setRequestHeader("Content-Type", "text/plain"); xhr.send(JSON.stringify(data)); @@ -1573,17 +1579,25 @@ } const specialTypesText = { - doubleLetter: _("Double\nLetter"), - doubleWord: _("Double\nWord"), - tripleLetter: _("Triple\nLetter"), - tripleWord: _("Triple\nWord") + doubleLetter: "Double\nLetter", + doubleWord: "Double\nWord", + tripleLetter: "Triple\nLetter", + tripleWord: "Triple\nWord" + }; + + const specialTypesShortText = { + doubleLetter: "DL", + doubleWord: "DW", + tripleLetter: "TL", + tripleWord: "TW" }; function specialCell(type, cell) { cell.firstChild.appendChild(document.createElement("span")); cell.classList.add("special-cell"); cell.classList.add("special-cell-" + type); - cell.lastChild.lastChild.textContent = cell.title = _(specialTypesText[type]); + cell.lastChild.lastChild.longText = cell.title = _(specialTypesText[type]); + cell.lastChild.lastChild.shortText = _(specialTypesShortText[type]); cell.lastChild.lastChild.className = "special-cell-label"; } @@ -2316,7 +2330,7 @@ setTimerState(document.getElementById("enable-timer").checked); }; - setTimerState(getSetting("TimerEnable", getSetting("ENABLE_TIMER"))); + setTimerState(getSetting("ENABLE_TIMER")); } let timerTimeout = 0; @@ -2328,7 +2342,7 @@ } function setTimerState(enabled) { - setSetting("TimerEnable", enabled); + setSetting("ENABLE_TIMER", enabled); if (timerTimeout) { clearInterval(timerTimeout); timerTimeout = 0; @@ -2346,6 +2360,32 @@ } } + function initCellCaptions() { + setCellCaptions(getSetting("CELL_CAPTIONS")); + + document.getElementById("cell-captions").onchange = function () { + setCellCaptions(document.getElementById("cell-captions").value); + setSetting("CELL_CAPTIONS", mode); + }; + } + + function setCellCaptions(mode) { + document.getElementById("cell-captions").value = mode; + + board.classList.remove("special-cell-label-short"); + board.classList.remove("special-cell-label-clip"); + board.classList.remove("special-cell-label-dots"); + board.classList.remove("special-cell-label-none"); + + for (const cell of [].slice.call(document.getElementsByClassName("special-cell-label"))) { + if (cell.textContent !== "★") { + cell.textContent = (mode === "short") ? cell.shortText : cell.longText; + } + } + + board.classList.add("special-cell-label-" + mode); + } + function repromptName(f) { if (getSetting("PlayerName") && getSetting("PlayerName").trim()) { f(); @@ -2465,6 +2505,7 @@ setSetting("PlayerName", name); } repromptName(initGame); + setCellCaptions(getSetting("CELL_CAPTIONS")); } ); @@ -2602,6 +2643,7 @@ initFlashLight(); nextHelpMessage(); initTimer(); + initCellCaptions(); }; trivabble.l10nError = trivabble.run;