Merge branch 'minimize_localstorage' into 'develop'

Minimize localstorage

See merge request raphj/trivabble!14
This commit is contained in:
Raphaël Jakse 2020-09-28 16:03:29 +00:00
commit 8fbc589ffe
2 changed files with 221 additions and 101 deletions

View File

@ -51,8 +51,8 @@
<span class="modal-button" id="btn-settings-close">&#215;</span>
</h2>
<div id="prefs">
<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="tiles-sound" /><span data-l10n="text-content">Sound of the tiles</span></label></p>
<p><label><input type="checkbox" id="msg-sound" /><span data-l10n="text-content">Sound of messages</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>
<p><label><span data-l10n="text-content">(fast)</span><input type="range" min="0" max="0" id="double-tap-duration"/><span data-l10n="text-content">(slow)</span><br/><span data-l10n="text-content">Double tap duration</span></label></p>
<p><label><span data-l10n="text-content">(fast)</span><input type="range" min="0" max="0" id="flash-light-duration"/><span data-l10n="text-content">(slow)</span><br/><span data-l10n="text-content">Flash light duration</span></label></p>

View File

@ -34,18 +34,125 @@
function setConf(parameterName, defaultValue) {
if (typeof Conf[parameterName] === "undefined") {
Conf[parameterName] = defaultValue;
} else if (typeof Conf[parameterName] !== typeof defaultValue) {
myAlert("Head's up - configuration " + parameterName + " does not have the right type. It should be a " + (typeof defaultValue) + ", it is a " + (typeof Conf[parameterName]));
throw new Error("Wrong type for configuration " + parameterName + ", expected " + (typeof defaultValue) + ", got " + (typeof Conf[parameterName]));
}
}
setConf("POLLING_DELAY", 2000);
setConf("ENABLE_WEBSOCKETS", true);
setConf("ENABLE_EVENT_SOURCE", true);
setConf("MAX_WEBSOCKET_ERRORS", 1);
setConf("APP_PATH", "");
setConf("ENABLE_SPELL_CHECKER", false);
setConf("DOUBLE_TAP_DURATIONS", [650, 1100, 1800, 3000, 5000]);
setConf("POLLING_DELAY", 2000);
setConf("ENABLE_WEBSOCKETS", true);
setConf("ENABLE_EVENT_SOURCE", true);
setConf("MAX_WEBSOCKET_ERRORS", 1);
setConf("APP_PATH", "");
setConf("ENABLE_MSG_SOUND", true);
setConf("ENABLE_TILE_SOUND", true);
setConf("ENABLE_SPELL_CHECKER", false);
setConf("DOUBLE_TAP_DURATIONS", [650, 1100, 1800, 3000, 5000]);
setConf("FLASH_LIGHT_DURATIONS", [800, 1600, 3200]);
setConf("FLASH_LIGHT_COLOR", "#E3E");
setConf("FLASH_LIGHT_COLOR", "#E3E");
function isSetting(key) {
return Object.prototype.hasOwnProperty.call(Conf, key) ||
Object.prototype.hasOwnProperty.call(localStorage, key);
}
function getSetting(key) {
let type;
let value;
/* get default value from configuration */
if (Object.prototype.hasOwnProperty.call(Conf, key)) {
value = Conf[key];
type = typeof value;
}
/* try to retrieve value from localstorage */
if (Object.prototype.hasOwnProperty.call(localStorage, key)) {
value = localStorage.getItem(key);
/* get type from localStorage if no default is set */
if (typeof type === "undefined") {
if (Object.prototype.hasOwnProperty.call(localStorage, key + "_type")) {
type = localStorage.getItem(key + "_type");
} else {
type = "string";
}
}
/* cast from string to type */
if (type === "boolean") {
value = (value === "true");
} else if (type === "number") {
value = Number(value);
} else if (type === "object") {
value = JSON.parse(value);
} else if (type === "string") {
value = String(value);
} else {
console.error("Unsupported type");
}
}
return value;
}
function setSetting(key, value) {
let type;
/* try to retrieve type from configuration */
if (Object.prototype.hasOwnProperty.call(Conf, key)) {
type = typeof Conf[key];
}
/* try to retrieve type from localstorage */
if (typeof type === "undefined") {
if (Object.prototype.hasOwnProperty.call(localStorage, key)) {
type = localStorage.getItem(key + "_type");
}
}
/* if not set type is defined from value */
if (typeof type === "undefined") {
type = typeof value;
}
/* storage value in localstorage */
if (type === typeof value) {
if (type === "object") {
value = JSON.stringify(value);
}
if ((type === "boolean") ||
(type === "number") ||
(type === "object") ||
(type === "string")) {
localStorage.setItem(key, value);
/* store type into localstorage if no default value in configuration */
if (!Object.prototype.hasOwnProperty.call(Conf, key)) {
localStorage.setItem(key + "_type", type);
}
} else {
console.error("Unsupported type");
}
} else {
console.error("incoherent type");
}
}
function migrateSetting(key, type) {
if (Object.prototype.hasOwnProperty.call(localStorage, key)) {
localStorage.setItem(key + "_type", type);
}
}
migrateSetting("doubleTapDuration", "number");
migrateSetting("flashLightDuration", "number");
migrateSetting("spellCheckerEnabled", "boolean");
migrateSetting("trivabbleGameNumber", "number");
migrateSetting("trivabbleBoardLang", "string");
migrateSetting("trivabbleGameNumber", "number");
migrateSetting("trivabbleLang", "string");
migrateSetting("trivabblePlayerName", "string");
const _ = (window.libD && libD.l10n) ? libD.l10n() : function (s) {
return s;
@ -167,11 +274,11 @@
return;
}
if (!force && localStorage.spellCheckerEnabled !== "true") {
if (!force && !getSetting("spellCheckerEnabled")) {
myConfirm(
_("Spell checking requires Trivabble to download a dictionary. Do you confirm?"),
function () {
localStorage.spellCheckerEnabled = "true";
setSetting("spellCheckerEnabled", true);
getDictionary(code, callback, true);
}
);
@ -205,7 +312,7 @@
}
function spellCheckerSettingChecked() {
localStorage.spellCheckerEnabled = document.getElementById("enable-spell-checker").checked.toString();
setSetting("spellCheckerEnabled", document.getElementById("enable-spell-checker").checked);
initSpellChecker();
}
@ -566,7 +673,7 @@
tile.lastChild.textContent = scoreOf[letter] || "";
if (highlight) {
tile.classList.add("tile-highlight");
if (tilesSound.checked) {
if (getSetting("ENABLE_TILE_SOUND")) {
audioNotification.play();
}
} else {
@ -633,14 +740,16 @@
function set(key, value) {
switch (key) {
case "playerName":
name.textContent = localStorage.trivabblePlayerName = value;
name.textContent = value;
setSetting("trivabblePlayerName", value);
break;
case "gameNumber":
document.getElementById("number").textContent = localStorage.trivabbleGameNumber = value;
document.getElementById("number").textContent = value;
setSetting("trivabbleGameNumber", value);
break;
case "boardLang":
localStorage.trivabbleBoardLang = value;
document.getElementById("board-lang").value = value;
setSetting("trivabbleBoardLang", value);
break;
}
}
@ -656,7 +765,7 @@
myAlert(
format(
_("You are about to leave the current game. To recover it, please note its number: {0}"),
localStorage.trivabbleGameNumber
getSetting("trivabbleGameNumber")
),
f
);
@ -736,8 +845,8 @@
chatMessages.scrollTop = chatMessages.scrollHeight;
if (sender && sender !== localStorage.trivabblePlayerName) {
if (msgSound.checked) {
if (sender && sender !== getSetting("trivabblePlayerName")) {
if (getSetting("ENABLE_MSG_SOUND")) {
audioChat.play();
}
@ -776,7 +885,7 @@
case "changeBoardLang": {
const newLang = boardLangSelect.querySelector("[value=" + msg.specialMsg.newBoardLang + "]").textContent;
infoMessage(
(msg.sender === localStorage.trivabblePlayerName)
(msg.sender === getSetting("trivabblePlayerName"))
? format(_("You changed the language of the board to {0}"), newLang)
: format(_("{0} changed the language of the board to {1}"), msg.sender, newLang)
);
@ -963,13 +1072,13 @@
}
if (data.to === "board") {
setCell(data.indexTo, data.letter, Object.prototype.hasOwnProperty.call(data, "player") && data.player !== localStorage.trivabblePlayerName);
setCell(data.indexTo, data.letter, Object.prototype.hasOwnProperty.call(data, "player") && data.player !== getSetting("trivabblePlayerName"));
} else if (data.to === "rack") {
setRackCell(data.indexTo, data.letter);
}
break;
case "setCell":
setCell(data.indexTo, data.letter, Object.prototype.hasOwnProperty.call(data, "player") && data.player !== localStorage.trivabblePlayerName);
setCell(data.indexTo, data.letter, Object.prototype.hasOwnProperty.call(data, "player") && data.player !== getSetting("trivabblePlayerName"));
if ((data.letter !== "") && (currentTilePlayed[data.indexTo] === "-")) {
currentTilePlayed[data.indexTo] = data.letter;
}
@ -1031,7 +1140,7 @@
}
if (data.gameNumber) {
set("gameNumber", data.gameNumber);
set("gameNumber", Number(data.gameNumber));
}
if (data.availableBoardLangs) {
@ -1099,7 +1208,7 @@
startConnection();
retryPollingTimeout = 0;
},
delay || Conf.POLLING_DELAY
delay || getSetting("POLLING_DELAY")
);
} else {
retriedImmediately = true;
@ -1176,7 +1285,7 @@
} else {
webSocketErrors++;
if (webSocketErrors > Conf.MAX_WEBSOCKET_ERRORS) {
if (webSocketErrors > getSetting("MAX_WEBSOCKET_ERRORS")) {
blacklistWebsockets = true;
}
}
@ -1203,7 +1312,7 @@
}
function pollServerWithEventSource() {
if (canConnect() && Conf.ENABLE_EVENT_SOURCE && window.EventSource) {
if (canConnect() && getSetting("ENABLE_EVENT_SOURCE") && window.EventSource) {
closeConnections();
pollingServer = true;
@ -1216,7 +1325,7 @@
}
function pollServerWithWebSocket() {
if (canConnect() && Conf.ENABLE_WEBSOCKETS && !blacklistWebsockets && window.WebSocket) {
if (canConnect() && getSetting("ENABLE_WEBSOCKETS") && !blacklistWebsockets && window.WebSocket) {
closeConnections();
pollingServer = true;
@ -1318,7 +1427,7 @@
xhrRequest(cmdsWithContext(cmds), function (xhr) {
if (xhr.readyState === 4) {
if (xhr.status === 0 || xhr.status >= 300) {
setTimeout(sendCmds.bind(null, cmds), Conf.POLLING_DELAY);
setTimeout(sendCmds.bind(null, cmds), getSetting("POLLING_DELAY"));
return;
}
@ -1335,9 +1444,9 @@
function cmdsWithContext(cmds) {
return {
gameNumber: localStorage.trivabbleGameNumber || "",
playerName: localStorage.trivabblePlayerName,
boardLang: localStorage.trivabbleBoardLang,
gameNumber: getSetting("trivabbleGameNumber") || "",
playerName: getSetting("trivabblePlayerName"),
boardLang: getSetting("trivabbleBoardLang"),
version: VERSION,
cmds: cmds
};
@ -1358,7 +1467,7 @@
if (!pollingReady) {
startConnection();
setTimeout(sendCmds, Conf.POLLING_DELAY, cmds);
setTimeout(sendCmds, getSetting("POLLING_DELAY"), cmds);
return;
}
@ -1369,13 +1478,13 @@
checkGameInProgress(
function () {
myPrompt(
_("To join a game, please give the number which is displayed on your adversary(ies)' screen.\nIf you do not know it, ask them.\n\nWarning: your adversary must not take your number, (s)he must keep his/her own. If you whish to recover your current game, please not the following number: {0}.").replace("{0}", localStorage.trivabbleGameNumber),
_("To join a game, please give the number which is displayed on your adversary(ies)' screen.\nIf you do not know it, ask them.\n\nWarning: your adversary must not take your number, (s)he must keep his/her own. If you whish to recover your current game, please not the following number: {0}.").replace("{0}", getSetting("trivabbleGameNumber")),
function (n) {
n = parseInt(n);
if (isNaN(n)) {
myAlert(_("It seems your did not give a correct number, or you clicked on “Cancel”. As a result, the current game continues, if any. To join a game, click on “Join a game” again."));
} else {
localStorage.trivabbleGameNumber = n;
setSetting("trivabbleGameNumber", n);
location.reload();
}
}
@ -1404,33 +1513,31 @@
_("To change your name, enter a new one. You can keep using your current name by cancelling. Please note that if you change your name and you have games in progress, you will not be able to keep playing them anymore unless you get back to your current name."),
function (newName) {
if (newName && newName.trim()) {
localStorage.trivabblePlayerName = newName.trim();
name.textContent = localStorage.trivabblePlayerName;
setSetting("trivabblePlayerName", newName.trim());
name.textContent = getSetting("trivabblePlayerName");
}
},
localStorage.trivabblePlayerName
getSetting("trivabblePlayerNamer")
);
}
function startGame(number) {
if (number) {
localStorage.trivabbleGameNumber = number;
setSetting("trivabbleGameNumber", number);
}
startConnection();
}
let audioTileLoaded = false;
let audioMsgLoaded = false;
let tilesSound;
let msgSound;
function loadAudio() {
if (!audioTileLoaded && tilesSound.checked) {
if (!audioTileLoaded && getSetting("ENABLE_TILE_SOUND")) {
audioTileLoaded = true;
audioNotification.load();
}
if (!audioMsgLoaded && msgSound.checked) {
if (!audioMsgLoaded && getSetting("ENABLE_MSG_SOUND")) {
audioMsgLoaded = true;
audioChat.load();
}
@ -1484,7 +1591,7 @@
sendCmds([{cmd: "changeBoard", lang: code}]);
},
function () {
boardLangSelect.value = localStorage.trivabbleBoardLang;
boardLangSelect.value = getSetting("trivabbleBoardLang");
}
);
}
@ -1668,11 +1775,11 @@
}
function checkSpellingClicked() {
if (localStorage.spellCheckerEnabled === "false") {
if (getSetting("spellCheckerEnabled") === "false") {
return;
}
getDictionary(localStorage.trivabbleBoardLang, checkSpelling);
getDictionary(getSetting("trivabbleBoardLang"), checkSpelling);
}
function checkSpelling(dictionary) {
@ -1761,7 +1868,7 @@
return;
}
if ((laserTouch.last !== cell) || (Date.now() - laserTouch.date > localStorage.doubleTapDuration)) {
if ((laserTouch.last !== cell) || (Date.now() - laserTouch.date > getSetting("doubleTapDuration"))) {
laserTouch.last = cell;
laserTouch.date = Date.now();
return;
@ -1775,7 +1882,7 @@
placeholder.classList.add("laser-highlighting");
placeholder.classList.add("laser-highlight");
const sixthFlashLightDuration = Number(localStorage.flashLightDuration) / 6;
const sixthFlashLightDuration = getSetting("flashLightDuration") / 6;
function on() {
placeholder.classList.add("laser-highlight");
@ -1854,39 +1961,47 @@
audioChat.appendChild(audioSourceOGG);
audioChat.appendChild(audioSourceMP3);
const tilesSound = document.getElementById("tiles-sound");
if (tilesSound) {
tilesSound = document.getElementById("tiles-sound");
msgSound = document.getElementById("msg-sound");
/* migration of old settings for tiles sound */
const oldSetting = getSetting("trivabbleTilesSound");
if (oldSetting) {
setSetting("ENABLE_TILE_SOUND", oldSetting === "true");
delete localStorage.trivabbleTilesSound;
}
tilesSound.onclick = function () {
localStorage.trivabbleTileSound = tilesSound.checked;
};
msgSound.onclick = function () {
localStorage.trivabbleMsgSound = msgSound.checked;
};
if (Object.prototype.hasOwnProperty.call(localStorage, "trivabbleMsgSound")) {
msgSound.checked = localStorage.trivabbleMsgSound === "true";
} else {
localStorage.trivabbleMsgSound = msgSound.checked;
tilesSound.checked = getSetting("ENABLE_TILE_SOUND");
tilesSound.onclick = function () {
setSetting("ENABLE_TILE_SOUND", this.checked);
};
}
if (Object.prototype.hasOwnProperty.call(localStorage, "trivabbleTileSound")) {
tilesSound.checked = localStorage.trivabbleTileSound === "true";
} else {
localStorage.trivabbleTilesSound = tilesSound.checked;
const msgSound = document.getElementById("msg-sound");
if (msgSound) {
/* migration of old settings for message sound */
const oldSetting = getSetting("trivabbleMsgSound");
if (oldSetting) {
setSetting("ENABLE_MSG_SOUND", oldSetting === "true");
delete localStorage.trivabbleMsgSound;
}
msgSound.checked = getSetting("ENABLE_MSG_SOUND");
msgSound.onclick = function () {
setSetting("ENABLE_MSG_SOUND", this.checked);
};
}
}
function initSpellChecker() {
if (Conf.ENABLE_SPELL_CHECKER) {
if (getSetting("ENABLE_SPELL_CHECKER")) {
document.getElementById("enable-spell-checker-outer").style.display = "";
}
document.getElementById("enable-spell-checker").onclick = spellCheckerSettingChecked;
if (!Conf.ENABLE_SPELL_CHECKER || localStorage.spellCheckerEnabled === "false") {
if (!getSetting("ENABLE_SPELL_CHECKER") || !getSetting("spellCheckerEnabled")) {
document.getElementById("check-spelling").style.display = "none";
document.getElementById("enable-spell-checker").checked = false;
document.getElementById("info-spell-checking").style.display = "none";
@ -1918,46 +2033,51 @@
document.body.addEventListener("dblclick", laserDblClick);
document.body.addEventListener("touchstart", laserTouch);
if (!Object.prototype.hasOwnProperty.call(localStorage, "doubleTapDuration")) {
localStorage.doubleTapDuration = Conf.DOUBLE_TAP_DURATIONS[Math.floor(Conf.DOUBLE_TAP_DURATIONS.length / 2)];
if (!isSetting("doubleTapDuration")) {
setSetting("doubleTapDuration", getSetting("DOUBLE_TAP_DURATIONS")[Math.floor(getSetting("DOUBLE_TAP_DURATIONS").length / 2)]);
}
const doubleTapDuration = document.getElementById("double-tap-duration");
if (doubleTapDuration) {
doubleTapDuration.max = Conf.DOUBLE_TAP_DURATIONS.length - 1;
doubleTapDuration.value = translateDuration(localStorage.doubleTapDuration, Conf.DOUBLE_TAP_DURATIONS);
doubleTapDuration.max = getSetting("DOUBLE_TAP_DURATIONS").length - 1;
doubleTapDuration.value = translateDuration(getSetting("doubleTapDuration"), getSetting("DOUBLE_TAP_DURATIONS"));
doubleTapDuration.onchange = function () {
localStorage.doubleTapDuration = translateDuration(
setSetting("doubleTapDuration", translateDuration(
document.getElementById("double-tap-duration").value,
Conf.DOUBLE_TAP_DURATIONS
);
getSetting("DOUBLE_TAP_DURATIONS")
));
};
}
if (!Object.prototype.hasOwnProperty.call(localStorage, "flashLightDuration")) {
localStorage.flashLightDuration = Conf.FLASH_LIGHT_DURATIONS[Math.floor(Conf.FLASH_LIGHT_DURATIONS.length / 2)];
if (!isSetting("flashLightDuration")) {
setSetting("flashLightDuration", getSetting("FLASH_LIGHT_DURATIONS")[Math.floor(getSetting("FLASH_LIGHT_DURATIONS").length / 2)]);
}
const flashLightDuration = document.getElementById("flash-light-duration");
if (flashLightDuration) {
flashLightDuration.max = Conf.FLASH_LIGHT_DURATIONS.length - 1;
flashLightDuration.value = translateDuration(localStorage.flashLightDuration, Conf.FLASH_LIGHT_DURATIONS);
flashLightDuration.max = getSetting("FLASH_LIGHT_DURATIONS").length - 1;
flashLightDuration.value = translateDuration(getSetting("flashLightDuration"), getSetting("FLASH_LIGHT_DURATIONS"));
flashLightDuration.onchange = function () {
localStorage.flashLightDuration = translateDuration(
setSetting("flashLightDuration", translateDuration(
document.getElementById("flash-light-duration").value,
Conf.FLASH_LIGHT_DURATIONS
);
getSetting("FLASH_LIGHT_DURATIONS")
));
};
}
if (!Object.prototype.hasOwnProperty.call(localStorage, "flashLightColor")) {
localStorage.flashLightColor = Conf.FLASH_LIGHT_COLOR;
}
const flashLightColor = document.getElementById("flash-light-color");
if (flashLightColor) {
flashLightColor.value = localStorage.flashLightColor;
/* migration of old settings for flash light color */
const oldSetting = getSetting("flashLightColor");
if (oldSetting) {
setSetting("FLASH_LIGHT_COLOR", oldSetting);
delete localStorage.flashLightColor;
}
flashLightColor.value = getSetting("FLASH_LIGHT_COLOR");
flashLightColor.onchange = function () {
localStorage.flashLightColor = document.getElementById("flash-light-color").value;
setSetting("FLASH_LIGHT_COLOR", document.getElementById("flash-light-color").value);
const style = document.createElement("style");
style.textContent = ".laser-highlight {background-color: " + localStorage.flashLightColor + ";}";
style.textContent = ".laser-highlight {background-color: " + getSetting("FLASH_LIGHT_COLOR") + ";}";
document.body.appendChild(style);
};
flashLightColor.onchange();
@ -1965,14 +2085,14 @@
}
function repromptName(f) {
if (localStorage.trivabblePlayerName && localStorage.trivabblePlayerName.trim()) {
if (getSetting("trivabblePlayerName") && getSetting("trivabblePlayerName").trim()) {
f();
} else {
myPrompt(
_("It seems your did not give your name. You need to do it for the game to run properly."),
function (name) {
if (name && name.trim()) {
localStorage.trivabblePlayerName = name.trim();
setSetting("trivabblePlayerName", name.trim());
}
repromptName(f);
@ -2021,11 +2141,11 @@
);
});
boardLangSelect.value = localStorage.trivabbleBoardLang;
boardLangSelect.value = getSetting("trivabbleBoardLang");
}
function langSelectionChange(e) {
localStorage.trivabbleLang = e.target.value;
setSetting("trivabbleLang", e.target.value);
location.reload();
}
@ -2064,12 +2184,12 @@
}
function initGame() {
if (!localStorage.trivabblePlayerName) {
if (!getSetting("trivabblePlayerName")) {
myPrompt(
_("Hello! To begin, enter your name. Your adversaries will see this name when you play with them."),
function (name) {
if (name && name.trim()) {
localStorage.trivabblePlayerName = name;
setSetting("trivabblePlayerName", name);
}
repromptName(initGame);
}
@ -2078,7 +2198,7 @@
return;
}
name.textContent = localStorage.trivabblePlayerName;
name.textContent = getSetting("trivabblePlayerName");
const letters = "ABCDEFGHIJKLMNO";
@ -2153,19 +2273,19 @@
board.lastChild.appendChild(board.rows[0].cells[0].cloneNode(false));
if (localStorage.trivabbleGameNumber) {
document.getElementById("number").textContent = localStorage.trivabbleGameNumber;
if (getSetting("trivabbleGameNumber")) {
document.getElementById("number").textContent = getSetting("trivabbleGameNumber");
}
if (localStorage.trivabbleBoardLang) {
document.getElementById("board-lang").value = localStorage.trivabbleBoardLang;
if (getSetting("trivabbleBoardLang")) {
document.getElementById("board-lang").value = getSetting("trivabbleBoardLang");
}
startGame(localStorage.trivabbleGameNumber);
startGame(getSetting("trivabbleGameNumber"));
}
function initLang() {
const lang = libD.lang = localStorage.trivabbleLang || libD.lang;
const lang = libD.lang = getSetting("trivabbleLang") || libD.lang;
const langSel = document.getElementById("select-lang");
langSel.value = lang;