mirror of
https://github.com/tobspr/shapez.io.git
synced 2026-03-02 03:39:21 +00:00
Cleanup IS_DEMO flags and introduce Restriction Manager
This commit is contained in:
@@ -1,179 +1,173 @@
|
||||
import { TextualGameState } from "../core/textual_game_state";
|
||||
import { SOUNDS } from "../platform/sound";
|
||||
import { T } from "../translations";
|
||||
import { KEYMAPPINGS, getStringForKeyCode } from "../game/key_action_mapper";
|
||||
import { Dialog } from "../core/modal_dialog_elements";
|
||||
import { IS_DEMO } from "../core/config";
|
||||
|
||||
export class KeybindingsState extends TextualGameState {
|
||||
constructor() {
|
||||
super("KeybindingsState");
|
||||
}
|
||||
|
||||
getStateHeaderTitle() {
|
||||
return T.keybindings.title;
|
||||
}
|
||||
|
||||
getMainContentHTML() {
|
||||
return `
|
||||
|
||||
<div class="topEntries">
|
||||
<span class="hint">${T.keybindings.hint}</span>
|
||||
<button class="styledButton resetBindings">${T.keybindings.resetKeybindings}</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="keybindings">
|
||||
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
onEnter() {
|
||||
const keybindingsElem = this.htmlElement.querySelector(".keybindings");
|
||||
|
||||
this.trackClicks(this.htmlElement.querySelector(".resetBindings"), this.resetBindings);
|
||||
|
||||
for (const category in KEYMAPPINGS) {
|
||||
const categoryDiv = document.createElement("div");
|
||||
categoryDiv.classList.add("category");
|
||||
keybindingsElem.appendChild(categoryDiv);
|
||||
|
||||
const labelDiv = document.createElement("strong");
|
||||
labelDiv.innerText = T.keybindings.categoryLabels[category];
|
||||
labelDiv.classList.add("categoryLabel");
|
||||
categoryDiv.appendChild(labelDiv);
|
||||
|
||||
for (const keybindingId in KEYMAPPINGS[category]) {
|
||||
const mapped = KEYMAPPINGS[category][keybindingId];
|
||||
|
||||
const elem = document.createElement("div");
|
||||
elem.classList.add("entry");
|
||||
elem.setAttribute("data-keybinding", keybindingId);
|
||||
categoryDiv.appendChild(elem);
|
||||
|
||||
const title = document.createElement("span");
|
||||
title.classList.add("title");
|
||||
title.innerText = T.keybindings.mappings[keybindingId];
|
||||
elem.appendChild(title);
|
||||
|
||||
const mappingDiv = document.createElement("span");
|
||||
mappingDiv.classList.add("mapping");
|
||||
elem.appendChild(mappingDiv);
|
||||
|
||||
const editBtn = document.createElement("button");
|
||||
editBtn.classList.add("styledButton", "editKeybinding");
|
||||
|
||||
const resetBtn = document.createElement("button");
|
||||
resetBtn.classList.add("styledButton", "resetKeybinding");
|
||||
|
||||
if (mapped.builtin) {
|
||||
editBtn.classList.add("disabled");
|
||||
resetBtn.classList.add("disabled");
|
||||
} else {
|
||||
this.trackClicks(editBtn, () => this.editKeybinding(keybindingId));
|
||||
this.trackClicks(resetBtn, () => this.resetKeybinding(keybindingId));
|
||||
}
|
||||
elem.appendChild(editBtn);
|
||||
elem.appendChild(resetBtn);
|
||||
}
|
||||
}
|
||||
this.updateKeybindings();
|
||||
}
|
||||
|
||||
editKeybinding(id) {
|
||||
// if (IS_DEMO) {
|
||||
// this.dialogs.showFeatureRestrictionInfo(T.demo.features.customizeKeybindings);
|
||||
// return;
|
||||
// }
|
||||
|
||||
const dialog = new Dialog({
|
||||
app: this.app,
|
||||
title: T.dialogs.editKeybinding.title,
|
||||
contentHTML: T.dialogs.editKeybinding.desc,
|
||||
buttons: ["cancel:good"],
|
||||
type: "info",
|
||||
});
|
||||
|
||||
dialog.inputReciever.keydown.add(({ keyCode, shift, alt, event }) => {
|
||||
if (keyCode === 27) {
|
||||
this.dialogs.closeDialog(dialog);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (event.target && event.target.tagName === "BUTTON" && keyCode === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
// Enter
|
||||
keyCode === 13
|
||||
) {
|
||||
// Ignore builtins
|
||||
return;
|
||||
}
|
||||
|
||||
this.app.settings.updateKeybindingOverride(id, keyCode);
|
||||
|
||||
this.dialogs.closeDialog(dialog);
|
||||
this.updateKeybindings();
|
||||
});
|
||||
|
||||
dialog.inputReciever.backButton.add(() => {});
|
||||
this.dialogs.internalShowDialog(dialog);
|
||||
|
||||
this.app.sound.playUiSound(SOUNDS.dialogOk);
|
||||
}
|
||||
|
||||
updateKeybindings() {
|
||||
const overrides = this.app.settings.getKeybindingOverrides();
|
||||
for (const category in KEYMAPPINGS) {
|
||||
for (const keybindingId in KEYMAPPINGS[category]) {
|
||||
const mapped = KEYMAPPINGS[category][keybindingId];
|
||||
|
||||
const container = this.htmlElement.querySelector("[data-keybinding='" + keybindingId + "']");
|
||||
assert(container, "Container for keybinding not found: " + keybindingId);
|
||||
|
||||
let keyCode = mapped.keyCode;
|
||||
if (overrides[keybindingId]) {
|
||||
keyCode = overrides[keybindingId];
|
||||
}
|
||||
|
||||
const mappingDiv = container.querySelector(".mapping");
|
||||
mappingDiv.innerHTML = getStringForKeyCode(keyCode);
|
||||
mappingDiv.classList.toggle("changed", !!overrides[keybindingId]);
|
||||
|
||||
const resetBtn = container.querySelector("button.resetKeybinding");
|
||||
resetBtn.classList.toggle("disabled", mapped.builtin || !overrides[keybindingId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resetKeybinding(id) {
|
||||
this.app.settings.resetKeybindingOverride(id);
|
||||
this.updateKeybindings();
|
||||
}
|
||||
|
||||
resetBindings() {
|
||||
const { reset } = this.dialogs.showWarning(
|
||||
T.dialogs.resetKeybindingsConfirmation.title,
|
||||
T.dialogs.resetKeybindingsConfirmation.desc,
|
||||
["cancel:good", "reset:bad"]
|
||||
);
|
||||
|
||||
reset.add(() => {
|
||||
this.app.settings.resetKeybindingOverrides();
|
||||
this.updateKeybindings();
|
||||
|
||||
this.dialogs.showInfo(T.dialogs.keybindingsResetOk.title, T.dialogs.keybindingsResetOk.desc);
|
||||
});
|
||||
}
|
||||
|
||||
getDefaultPreviousState() {
|
||||
return "SettingsState";
|
||||
}
|
||||
}
|
||||
import { Dialog } from "../core/modal_dialog_elements";
|
||||
import { TextualGameState } from "../core/textual_game_state";
|
||||
import { getStringForKeyCode, KEYMAPPINGS } from "../game/key_action_mapper";
|
||||
import { SOUNDS } from "../platform/sound";
|
||||
import { T } from "../translations";
|
||||
|
||||
export class KeybindingsState extends TextualGameState {
|
||||
constructor() {
|
||||
super("KeybindingsState");
|
||||
}
|
||||
|
||||
getStateHeaderTitle() {
|
||||
return T.keybindings.title;
|
||||
}
|
||||
|
||||
getMainContentHTML() {
|
||||
return `
|
||||
|
||||
<div class="topEntries">
|
||||
<span class="hint">${T.keybindings.hint}</span>
|
||||
<button class="styledButton resetBindings">${T.keybindings.resetKeybindings}</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="keybindings">
|
||||
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
onEnter() {
|
||||
const keybindingsElem = this.htmlElement.querySelector(".keybindings");
|
||||
|
||||
this.trackClicks(this.htmlElement.querySelector(".resetBindings"), this.resetBindings);
|
||||
|
||||
for (const category in KEYMAPPINGS) {
|
||||
const categoryDiv = document.createElement("div");
|
||||
categoryDiv.classList.add("category");
|
||||
keybindingsElem.appendChild(categoryDiv);
|
||||
|
||||
const labelDiv = document.createElement("strong");
|
||||
labelDiv.innerText = T.keybindings.categoryLabels[category];
|
||||
labelDiv.classList.add("categoryLabel");
|
||||
categoryDiv.appendChild(labelDiv);
|
||||
|
||||
for (const keybindingId in KEYMAPPINGS[category]) {
|
||||
const mapped = KEYMAPPINGS[category][keybindingId];
|
||||
|
||||
const elem = document.createElement("div");
|
||||
elem.classList.add("entry");
|
||||
elem.setAttribute("data-keybinding", keybindingId);
|
||||
categoryDiv.appendChild(elem);
|
||||
|
||||
const title = document.createElement("span");
|
||||
title.classList.add("title");
|
||||
title.innerText = T.keybindings.mappings[keybindingId];
|
||||
elem.appendChild(title);
|
||||
|
||||
const mappingDiv = document.createElement("span");
|
||||
mappingDiv.classList.add("mapping");
|
||||
elem.appendChild(mappingDiv);
|
||||
|
||||
const editBtn = document.createElement("button");
|
||||
editBtn.classList.add("styledButton", "editKeybinding");
|
||||
|
||||
const resetBtn = document.createElement("button");
|
||||
resetBtn.classList.add("styledButton", "resetKeybinding");
|
||||
|
||||
if (mapped.builtin) {
|
||||
editBtn.classList.add("disabled");
|
||||
resetBtn.classList.add("disabled");
|
||||
} else {
|
||||
this.trackClicks(editBtn, () => this.editKeybinding(keybindingId));
|
||||
this.trackClicks(resetBtn, () => this.resetKeybinding(keybindingId));
|
||||
}
|
||||
elem.appendChild(editBtn);
|
||||
elem.appendChild(resetBtn);
|
||||
}
|
||||
}
|
||||
this.updateKeybindings();
|
||||
}
|
||||
|
||||
editKeybinding(id) {
|
||||
const dialog = new Dialog({
|
||||
app: this.app,
|
||||
title: T.dialogs.editKeybinding.title,
|
||||
contentHTML: T.dialogs.editKeybinding.desc,
|
||||
buttons: ["cancel:good"],
|
||||
type: "info",
|
||||
});
|
||||
|
||||
dialog.inputReciever.keydown.add(({ keyCode, shift, alt, event }) => {
|
||||
if (keyCode === 27) {
|
||||
this.dialogs.closeDialog(dialog);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
if (event.target && event.target.tagName === "BUTTON" && keyCode === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
// Enter
|
||||
keyCode === 13
|
||||
) {
|
||||
// Ignore builtins
|
||||
return;
|
||||
}
|
||||
|
||||
this.app.settings.updateKeybindingOverride(id, keyCode);
|
||||
|
||||
this.dialogs.closeDialog(dialog);
|
||||
this.updateKeybindings();
|
||||
});
|
||||
|
||||
dialog.inputReciever.backButton.add(() => {});
|
||||
this.dialogs.internalShowDialog(dialog);
|
||||
|
||||
this.app.sound.playUiSound(SOUNDS.dialogOk);
|
||||
}
|
||||
|
||||
updateKeybindings() {
|
||||
const overrides = this.app.settings.getKeybindingOverrides();
|
||||
for (const category in KEYMAPPINGS) {
|
||||
for (const keybindingId in KEYMAPPINGS[category]) {
|
||||
const mapped = KEYMAPPINGS[category][keybindingId];
|
||||
|
||||
const container = this.htmlElement.querySelector("[data-keybinding='" + keybindingId + "']");
|
||||
assert(container, "Container for keybinding not found: " + keybindingId);
|
||||
|
||||
let keyCode = mapped.keyCode;
|
||||
if (overrides[keybindingId]) {
|
||||
keyCode = overrides[keybindingId];
|
||||
}
|
||||
|
||||
const mappingDiv = container.querySelector(".mapping");
|
||||
mappingDiv.innerHTML = getStringForKeyCode(keyCode);
|
||||
mappingDiv.classList.toggle("changed", !!overrides[keybindingId]);
|
||||
|
||||
const resetBtn = container.querySelector("button.resetKeybinding");
|
||||
resetBtn.classList.toggle("disabled", mapped.builtin || !overrides[keybindingId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resetKeybinding(id) {
|
||||
this.app.settings.resetKeybindingOverride(id);
|
||||
this.updateKeybindings();
|
||||
}
|
||||
|
||||
resetBindings() {
|
||||
const { reset } = this.dialogs.showWarning(
|
||||
T.dialogs.resetKeybindingsConfirmation.title,
|
||||
T.dialogs.resetKeybindingsConfirmation.desc,
|
||||
["cancel:good", "reset:bad"]
|
||||
);
|
||||
|
||||
reset.add(() => {
|
||||
this.app.settings.resetKeybindingOverrides();
|
||||
this.updateKeybindings();
|
||||
|
||||
this.dialogs.showInfo(T.dialogs.keybindingsResetOk.title, T.dialogs.keybindingsResetOk.desc);
|
||||
});
|
||||
}
|
||||
|
||||
getDefaultPreviousState() {
|
||||
return "SettingsState";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
import { GameState } from "../core/game_state";
|
||||
import { cachebust } from "../core/cachebust";
|
||||
import { A_B_TESTING_LINK_TYPE, globalConfig, IS_DEMO, THIRDPARTY_URLS } from "../core/config";
|
||||
import { A_B_TESTING_LINK_TYPE, globalConfig, THIRDPARTY_URLS } from "../core/config";
|
||||
import { GameState } from "../core/game_state";
|
||||
import { DialogWithForm } from "../core/modal_dialog_elements";
|
||||
import { FormElementInput } from "../core/modal_dialog_forms";
|
||||
import { ReadWriteProxy } from "../core/read_write_proxy";
|
||||
import {
|
||||
makeDiv,
|
||||
makeButtonElement,
|
||||
formatSecondsToTimeAgo,
|
||||
waitNextFrame,
|
||||
generateFileDownload,
|
||||
isSupportedBrowser,
|
||||
makeButton,
|
||||
makeButtonElement,
|
||||
makeDiv,
|
||||
removeAllChildren,
|
||||
startFileChoose,
|
||||
waitNextFrame,
|
||||
} from "../core/utils";
|
||||
import { ReadWriteProxy } from "../core/read_write_proxy";
|
||||
import { HUDModalDialogs } from "../game/hud/parts/modal_dialogs";
|
||||
import { T } from "../translations";
|
||||
import { getApplicationSettingById } from "../profile/application_settings";
|
||||
import { FormElementInput } from "../core/modal_dialog_forms";
|
||||
import { DialogWithForm } from "../core/modal_dialog_elements";
|
||||
import { T } from "../translations";
|
||||
|
||||
const trim = require("trim");
|
||||
|
||||
@@ -24,23 +26,6 @@ const trim = require("trim");
|
||||
* @typedef {import("../profile/setting_types").EnumSetting} EnumSetting
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generates a file download
|
||||
* @param {string} filename
|
||||
* @param {string} text
|
||||
*/
|
||||
function generateFileDownload(filename, text) {
|
||||
var element = document.createElement("a");
|
||||
element.setAttribute("href", "data:text/plain;charset=utf-8," + encodeURIComponent(text));
|
||||
element.setAttribute("download", filename);
|
||||
|
||||
element.style.display = "none";
|
||||
document.body.appendChild(element);
|
||||
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
}
|
||||
|
||||
export class MainMenuState extends GameState {
|
||||
constructor() {
|
||||
super("MainMenuState");
|
||||
@@ -49,18 +34,16 @@ export class MainMenuState extends GameState {
|
||||
getInnerHTML() {
|
||||
const bannerHtml = `
|
||||
<h3>${T.demoBanners.title}</h3>
|
||||
|
||||
<p>${T.demoBanners.intro}</p>
|
||||
|
||||
<a href="#" class="steamLink ${A_B_TESTING_LINK_TYPE}" target="_blank">Get the shapez.io standalone!</a>
|
||||
`;
|
||||
|
||||
return `
|
||||
const showDemoBadges = this.app.restrictionMgr.getIsStandaloneMarketingActive();
|
||||
|
||||
return `
|
||||
<div class="topButtons">
|
||||
<button class="languageChoose" data-languageicon="${this.app.settings.getLanguage()}"></button>
|
||||
<button class="settingsButton"></button>
|
||||
|
||||
${
|
||||
G_IS_STANDALONE || G_IS_DEV
|
||||
? `
|
||||
@@ -74,17 +57,14 @@ export class MainMenuState extends GameState {
|
||||
<source src="${cachebust("res/bg_render.webm")}" type="video/webm">
|
||||
</video>
|
||||
|
||||
|
||||
<div class="logo">
|
||||
<img src="${cachebust("res/logo.png")}" alt="shapez.io Logo">
|
||||
<span class="updateLabel">Wires update!</span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="mainWrapper ${IS_DEMO ? "demo" : "noDemo"}">
|
||||
|
||||
<div class="mainWrapper ${showDemoBadges ? "demo" : "noDemo"}">
|
||||
<div class="sideContainer">
|
||||
${IS_DEMO ? `<div class="standaloneBanner">${bannerHtml}</div>` : ""}
|
||||
${showDemoBadges ? `<div class="standaloneBanner">${bannerHtml}</div>` : ""}
|
||||
</div>
|
||||
|
||||
<div class="mainContainer">
|
||||
@@ -95,12 +75,9 @@ export class MainMenuState extends GameState {
|
||||
}
|
||||
<div class="buttons"></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
|
||||
<a class="githubLink boxLink" target="_blank">
|
||||
${T.mainMenu.openSourceHint}
|
||||
<span class="thirdpartyLogo githubLogo"></span>
|
||||
@@ -123,32 +100,29 @@ export class MainMenuState extends GameState {
|
||||
"<author-link>",
|
||||
'<a class="producerLink" target="_blank">Tobias Springer</a>'
|
||||
)}</div>
|
||||
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks the user to import a savegame
|
||||
*/
|
||||
requestImportSavegame() {
|
||||
if (
|
||||
IS_DEMO &&
|
||||
this.app.savegameMgr.getSavegamesMetaData().length > 0 &&
|
||||
!this.app.platformWrapper.getHasUnlimitedSavegames()
|
||||
!this.app.restrictionMgr.getHasUnlimitedSavegames()
|
||||
) {
|
||||
this.app.analytics.trackUiClick("importgame_slot_limit_show");
|
||||
this.showSavegameSlotLimit();
|
||||
return;
|
||||
}
|
||||
|
||||
var input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.accept = ".bin";
|
||||
|
||||
input.onchange = e => {
|
||||
const file = input.files[0];
|
||||
// Create a 'fake' file-input to accept savegames
|
||||
startFileChoose(".bin").then(file => {
|
||||
if (file) {
|
||||
const closeLoader = this.dialogs.showLoadingDialog();
|
||||
waitNextFrame().then(() => {
|
||||
this.app.analytics.trackUiClick("import_savegame");
|
||||
const closeLoader = this.dialogs.showLoadingDialog();
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener("load", event => {
|
||||
const contents = event.target.result;
|
||||
@@ -194,8 +168,7 @@ export class MainMenuState extends GameState {
|
||||
reader.readAsText(file, "utf-8");
|
||||
});
|
||||
}
|
||||
};
|
||||
input.click();
|
||||
});
|
||||
}
|
||||
|
||||
onBackButton() {
|
||||
@@ -557,9 +530,8 @@ export class MainMenuState extends GameState {
|
||||
|
||||
onPlayButtonClicked() {
|
||||
if (
|
||||
IS_DEMO &&
|
||||
this.app.savegameMgr.getSavegamesMetaData().length > 0 &&
|
||||
!this.app.platformWrapper.getHasUnlimitedSavegames()
|
||||
!this.app.restrictionMgr.getHasUnlimitedSavegames()
|
||||
) {
|
||||
this.app.analytics.trackUiClick("startgame_slot_limit_show");
|
||||
this.showSavegameSlotLimit();
|
||||
|
||||
@@ -1,169 +1,169 @@
|
||||
import { TextualGameState } from "../core/textual_game_state";
|
||||
import { formatSecondsToTimeAgo } from "../core/utils";
|
||||
import { allApplicationSettings, enumCategories } from "../profile/application_settings";
|
||||
import { T } from "../translations";
|
||||
|
||||
export class SettingsState extends TextualGameState {
|
||||
constructor() {
|
||||
super("SettingsState");
|
||||
}
|
||||
|
||||
getStateHeaderTitle() {
|
||||
return T.settings.title;
|
||||
}
|
||||
|
||||
getMainContentHTML() {
|
||||
return `
|
||||
|
||||
<div class="sidebar">
|
||||
${this.getCategoryButtonsHtml()}
|
||||
|
||||
${
|
||||
this.app.platformWrapper.getSupportsKeyboard()
|
||||
? `
|
||||
<button class="styledButton categoryButton editKeybindings">
|
||||
${T.keybindings.title}
|
||||
</button>`
|
||||
: ""
|
||||
}
|
||||
|
||||
<div class="other">
|
||||
<button class="styledButton about">${T.about.title}</button>
|
||||
|
||||
<div class="versionbar">
|
||||
<div class="buildVersion">${T.global.loading} ...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="categoryContainer">
|
||||
${this.getSettingsHtml()}
|
||||
</div>
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
getCategoryButtonsHtml() {
|
||||
return Object.keys(enumCategories)
|
||||
.map(key => enumCategories[key])
|
||||
.map(
|
||||
category =>
|
||||
`
|
||||
<button class="styledButton categoryButton" data-category-btn="${category}">
|
||||
${T.settings.categories[category]}
|
||||
</button>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
}
|
||||
|
||||
getSettingsHtml() {
|
||||
const categoriesHTML = {};
|
||||
|
||||
Object.keys(enumCategories).forEach(key => {
|
||||
const catName = enumCategories[key];
|
||||
categoriesHTML[catName] = `<div class="category" data-category="${catName}">`;
|
||||
});
|
||||
|
||||
for (let i = 0; i < allApplicationSettings.length; ++i) {
|
||||
const setting = allApplicationSettings[i];
|
||||
|
||||
categoriesHTML[setting.categoryId] += setting.getHtml();
|
||||
}
|
||||
|
||||
return Object.keys(categoriesHTML)
|
||||
.map(k => categoriesHTML[k] + "</div>")
|
||||
.join("");
|
||||
}
|
||||
|
||||
renderBuildText() {
|
||||
const labelVersion = this.htmlElement.querySelector(".buildVersion");
|
||||
const lastBuildMs = new Date().getTime() - G_BUILD_TIME;
|
||||
const lastBuildText = formatSecondsToTimeAgo(lastBuildMs / 1000.0);
|
||||
|
||||
const version = T.settings.versionBadges[G_APP_ENVIRONMENT];
|
||||
|
||||
labelVersion.innerHTML = `
|
||||
<span class='version'>
|
||||
${G_BUILD_VERSION} @ ${version} @ ${G_BUILD_COMMIT_HASH}
|
||||
</span>
|
||||
<span class='buildTime'>
|
||||
${T.settings.buildDate.replace("<at-date>", lastBuildText)}<br />
|
||||
</span>`;
|
||||
}
|
||||
|
||||
onEnter(payload) {
|
||||
this.renderBuildText();
|
||||
this.trackClicks(this.htmlElement.querySelector(".about"), this.onAboutClicked, {
|
||||
preventDefault: false,
|
||||
});
|
||||
|
||||
const keybindingsButton = this.htmlElement.querySelector(".editKeybindings");
|
||||
|
||||
if (keybindingsButton) {
|
||||
this.trackClicks(keybindingsButton, this.onKeybindingsClicked, { preventDefault: false });
|
||||
}
|
||||
|
||||
this.initSettings();
|
||||
this.initCategoryButtons();
|
||||
|
||||
this.htmlElement.querySelector(".category").classList.add("active");
|
||||
this.htmlElement.querySelector(".categoryButton").classList.add("active");
|
||||
}
|
||||
|
||||
setActiveCategory(category) {
|
||||
const previousCategory = this.htmlElement.querySelector(".category.active");
|
||||
const previousCategoryButton = this.htmlElement.querySelector(".categoryButton.active");
|
||||
|
||||
if (previousCategory.getAttribute("data-category") == category) {
|
||||
return;
|
||||
}
|
||||
|
||||
previousCategory.classList.remove("active");
|
||||
previousCategoryButton.classList.remove("active");
|
||||
|
||||
const newCategory = this.htmlElement.querySelector("[data-category='" + category + "']");
|
||||
const newCategoryButton = this.htmlElement.querySelector("[data-category-btn='" + category + "']");
|
||||
|
||||
newCategory.classList.add("active");
|
||||
newCategoryButton.classList.add("active");
|
||||
}
|
||||
|
||||
initSettings() {
|
||||
allApplicationSettings.forEach(setting => {
|
||||
/** @type {HTMLElement} */
|
||||
const element = this.htmlElement.querySelector("[data-setting='" + setting.id + "']");
|
||||
setting.bind(this.app, element, this.dialogs);
|
||||
setting.syncValueToElement();
|
||||
this.trackClicks(
|
||||
element,
|
||||
() => {
|
||||
setting.modify();
|
||||
},
|
||||
{ preventDefault: false }
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
initCategoryButtons() {
|
||||
Object.keys(enumCategories).forEach(key => {
|
||||
const category = enumCategories[key];
|
||||
const button = this.htmlElement.querySelector("[data-category-btn='" + category + "']");
|
||||
this.trackClicks(
|
||||
button,
|
||||
() => {
|
||||
this.setActiveCategory(category);
|
||||
},
|
||||
{ preventDefault: false }
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
onAboutClicked() {
|
||||
this.moveToStateAddGoBack("AboutState");
|
||||
}
|
||||
|
||||
onKeybindingsClicked() {
|
||||
this.moveToStateAddGoBack("KeybindingsState");
|
||||
}
|
||||
}
|
||||
import { TextualGameState } from "../core/textual_game_state";
|
||||
import { formatSecondsToTimeAgo } from "../core/utils";
|
||||
import { allApplicationSettings, enumCategories } from "../profile/application_settings";
|
||||
import { T } from "../translations";
|
||||
|
||||
export class SettingsState extends TextualGameState {
|
||||
constructor() {
|
||||
super("SettingsState");
|
||||
}
|
||||
|
||||
getStateHeaderTitle() {
|
||||
return T.settings.title;
|
||||
}
|
||||
|
||||
getMainContentHTML() {
|
||||
return `
|
||||
|
||||
<div class="sidebar">
|
||||
${this.getCategoryButtonsHtml()}
|
||||
|
||||
${
|
||||
this.app.platformWrapper.getSupportsKeyboard()
|
||||
? `
|
||||
<button class="styledButton categoryButton editKeybindings">
|
||||
${T.keybindings.title}
|
||||
</button>`
|
||||
: ""
|
||||
}
|
||||
|
||||
<div class="other">
|
||||
<button class="styledButton about">${T.about.title}</button>
|
||||
|
||||
<div class="versionbar">
|
||||
<div class="buildVersion">${T.global.loading} ...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="categoryContainer">
|
||||
${this.getSettingsHtml()}
|
||||
</div>
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
getCategoryButtonsHtml() {
|
||||
return Object.keys(enumCategories)
|
||||
.map(key => enumCategories[key])
|
||||
.map(
|
||||
category =>
|
||||
`
|
||||
<button class="styledButton categoryButton" data-category-btn="${category}">
|
||||
${T.settings.categories[category]}
|
||||
</button>
|
||||
`
|
||||
)
|
||||
.join("");
|
||||
}
|
||||
|
||||
getSettingsHtml() {
|
||||
const categoriesHTML = {};
|
||||
|
||||
Object.keys(enumCategories).forEach(key => {
|
||||
const catName = enumCategories[key];
|
||||
categoriesHTML[catName] = `<div class="category" data-category="${catName}">`;
|
||||
});
|
||||
|
||||
for (let i = 0; i < allApplicationSettings.length; ++i) {
|
||||
const setting = allApplicationSettings[i];
|
||||
|
||||
categoriesHTML[setting.categoryId] += setting.getHtml(this.app);
|
||||
}
|
||||
|
||||
return Object.keys(categoriesHTML)
|
||||
.map(k => categoriesHTML[k] + "</div>")
|
||||
.join("");
|
||||
}
|
||||
|
||||
renderBuildText() {
|
||||
const labelVersion = this.htmlElement.querySelector(".buildVersion");
|
||||
const lastBuildMs = new Date().getTime() - G_BUILD_TIME;
|
||||
const lastBuildText = formatSecondsToTimeAgo(lastBuildMs / 1000.0);
|
||||
|
||||
const version = T.settings.versionBadges[G_APP_ENVIRONMENT];
|
||||
|
||||
labelVersion.innerHTML = `
|
||||
<span class='version'>
|
||||
${G_BUILD_VERSION} @ ${version} @ ${G_BUILD_COMMIT_HASH}
|
||||
</span>
|
||||
<span class='buildTime'>
|
||||
${T.settings.buildDate.replace("<at-date>", lastBuildText)}<br />
|
||||
</span>`;
|
||||
}
|
||||
|
||||
onEnter(payload) {
|
||||
this.renderBuildText();
|
||||
this.trackClicks(this.htmlElement.querySelector(".about"), this.onAboutClicked, {
|
||||
preventDefault: false,
|
||||
});
|
||||
|
||||
const keybindingsButton = this.htmlElement.querySelector(".editKeybindings");
|
||||
|
||||
if (keybindingsButton) {
|
||||
this.trackClicks(keybindingsButton, this.onKeybindingsClicked, { preventDefault: false });
|
||||
}
|
||||
|
||||
this.initSettings();
|
||||
this.initCategoryButtons();
|
||||
|
||||
this.htmlElement.querySelector(".category").classList.add("active");
|
||||
this.htmlElement.querySelector(".categoryButton").classList.add("active");
|
||||
}
|
||||
|
||||
setActiveCategory(category) {
|
||||
const previousCategory = this.htmlElement.querySelector(".category.active");
|
||||
const previousCategoryButton = this.htmlElement.querySelector(".categoryButton.active");
|
||||
|
||||
if (previousCategory.getAttribute("data-category") == category) {
|
||||
return;
|
||||
}
|
||||
|
||||
previousCategory.classList.remove("active");
|
||||
previousCategoryButton.classList.remove("active");
|
||||
|
||||
const newCategory = this.htmlElement.querySelector("[data-category='" + category + "']");
|
||||
const newCategoryButton = this.htmlElement.querySelector("[data-category-btn='" + category + "']");
|
||||
|
||||
newCategory.classList.add("active");
|
||||
newCategoryButton.classList.add("active");
|
||||
}
|
||||
|
||||
initSettings() {
|
||||
allApplicationSettings.forEach(setting => {
|
||||
/** @type {HTMLElement} */
|
||||
const element = this.htmlElement.querySelector("[data-setting='" + setting.id + "']");
|
||||
setting.bind(this.app, element, this.dialogs);
|
||||
setting.syncValueToElement();
|
||||
this.trackClicks(
|
||||
element,
|
||||
() => {
|
||||
setting.modify();
|
||||
},
|
||||
{ preventDefault: false }
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
initCategoryButtons() {
|
||||
Object.keys(enumCategories).forEach(key => {
|
||||
const category = enumCategories[key];
|
||||
const button = this.htmlElement.querySelector("[data-category-btn='" + category + "']");
|
||||
this.trackClicks(
|
||||
button,
|
||||
() => {
|
||||
this.setActiveCategory(category);
|
||||
},
|
||||
{ preventDefault: false }
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
onAboutClicked() {
|
||||
this.moveToStateAddGoBack("AboutState");
|
||||
}
|
||||
|
||||
onKeybindingsClicked() {
|
||||
this.moveToStateAddGoBack("KeybindingsState");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user