diff --git a/src/js/savegame/savegame_manager.js b/src/js/savegame/savegame_manager.js
index 52f9dc14..587d173f 100644
--- a/src/js/savegame/savegame_manager.js
+++ b/src/js/savegame/savegame_manager.js
@@ -40,13 +40,6 @@ export class SavegameManager extends ReadWriteProxy {
return 1002;
}
- /**
- * @returns {SavegamesData}
- */
- getCurrentData() {
- return super.getCurrentData();
- }
-
verify(data) {
// TODO / FIXME!!!!
return ExplainedResult.good();
diff --git a/src/js/states/keybindings.js b/src/js/states/keybindings.js
index b68626c7..a01629f1 100644
--- a/src/js/states/keybindings.js
+++ b/src/js/states/keybindings.js
@@ -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 `
-
-
- ${T.keybindings.hint}
-
-
-
-
-
-
-
- `;
- }
-
- 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 `
+
+
+ ${T.keybindings.hint}
+
+
+
+
+
+
+
+ `;
+ }
+
+ 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";
+ }
+}
diff --git a/src/js/states/main_menu.js b/src/js/states/main_menu.js
index 0d186ffd..a3f06ca0 100644
--- a/src/js/states/main_menu.js
+++ b/src/js/states/main_menu.js
@@ -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 = `
${T.demoBanners.title}
-
${T.demoBanners.intro}
-
Get the shapez.io standalone!
`;
- return `
+ const showDemoBadges = this.app.restrictionMgr.getIsStandaloneMarketingActive();
+ return `