+
+ ${
+ G_IS_STANDALONE
+ ? ""
+ : `
+
${bannerHtml}
+ `
+ }
+
+
+
+
+
+ ${
+ G_IS_STANDALONE
+ ? ""
+ : `
+ ${bannerHtml}
+ `
+ }
+
@@ -45,6 +91,60 @@ export class MainMenuState extends GameState {
`;
}
+ requestImportSavegame() {
+ var input = document.createElement("input");
+ input.type = "file";
+ input.accept = ".bin";
+
+ input.onchange = e => {
+ const file = input.files[0];
+ if (file) {
+ waitNextFrame().then(() => {
+ const closeLoader = this.dialogs.showLoadingDialog();
+ const reader = new FileReader();
+ reader.addEventListener("load", event => {
+ const contents = event.target.result;
+
+ let realContent;
+
+ try {
+ realContent = ReadWriteProxy.deserializeObject(contents);
+ } catch (err) {
+ closeLoader();
+ this.dialogs.showWarning(
+ "Import error",
+ "Failed to import your savegame:
" + err + ); + return; + } + + this.app.savegameMgr.importSavegame(realContent).then( + () => { + closeLoader(); + this.dialogs.showWarning("Imported", "Your savegame has been imported."); + + this.renderSavegames(); + }, + err => { + closeLoader(); + this.dialogs.showWarning( + "Import error", + "Failed to import savegame. Please check the console output." + ); + } + ); + }); + reader.addEventListener("error", error => { + console.error(error); + alert("Failed to read file: " + error); + }); + reader.readAsText(file, "utf-8"); + }); + } + }; + input.click(); + } + onBackButton() { this.app.platformWrapper.exitApp(); } @@ -54,8 +154,13 @@ export class MainMenuState extends GameState { alert("Error while loading game: " + payload.loadError); } + this.dialogs = new HUDModalDialogs(null, this.app); + const dialogsElement = document.body.querySelector(".modalDialogParent"); + this.dialogs.initializeToElement(dialogsElement); + const qs = this.htmlElement.querySelector.bind(this.htmlElement); this.trackClicks(qs(".mainContainer .playButton"), this.onPlayButtonClicked); + this.trackClicks(qs(".mainContainer .importButton"), this.requestImportSavegame); if (G_IS_DEV && globalConfig.debug.fastGameEnter) { this.onPlayButtonClicked(); @@ -76,6 +181,10 @@ export class MainMenuState extends GameState { } renderSavegames() { + const oldContainer = this.htmlElement.querySelector(".mainContainer .savegames"); + if (oldContainer) { + oldContainer.remove(); + } const games = this.app.savegameMgr.getSavegamesMetaData(); if (games.length > 0) { const parent = makeDiv(this.htmlElement.querySelector(".mainContainer"), null, ["savegames"]); @@ -91,6 +200,10 @@ export class MainMenuState extends GameState { formatSecondsToTimeAgo((new Date().getTime() - games[i].lastUpdate) / 1000.0) ); + const deleteButton = document.createElement("button"); + deleteButton.classList.add("styledButton", "deleteGame"); + elem.appendChild(deleteButton); + const downloadButton = document.createElement("button"); downloadButton.classList.add("styledButton", "downloadGame"); elem.appendChild(downloadButton); @@ -99,6 +212,7 @@ export class MainMenuState extends GameState { resumeBtn.classList.add("styledButton", "resumeGame"); elem.appendChild(resumeBtn); + this.trackClicks(deleteButton, () => this.deleteGame(games[i])); this.trackClicks(downloadButton, () => this.downloadGame(games[i])); this.trackClicks(resumeBtn, () => this.resumeGame(games[i])); } @@ -117,6 +231,28 @@ export class MainMenuState extends GameState { }); } + /** + * @param {object} game + */ + deleteGame(game) { + const signals = this.dialogs.showWarning( + "Confirm Deletion", + "Are you sure you want to delete the game?", + ["delete:bad", "cancel:good"] + ); + + signals.delete.add(() => { + this.app.savegameMgr.deleteSavegame(game).then( + () => { + this.renderSavegames(); + }, + err => { + this.dialogs.showWarning("Failed to delete", "Error: " + err); + } + ); + }); + } + /** * @param {object} game */ @@ -138,6 +274,6 @@ export class MainMenuState extends GameState { } onLeave() { - // this.dialogs.cleanup(); + this.dialogs.cleanup(); } } diff --git a/src/js/states/preload.js b/src/js/states/preload.js index 6e885b15..b5857707 100644 --- a/src/js/states/preload.js +++ b/src/js/states/preload.js @@ -67,10 +67,6 @@ export class PreloadState extends GameState { .then(() => this.setStatus("Creating platform wrapper")) .then(() => this.app.platformWrapper.initialize()) - .then(() => this.setStatus("Initializing libraries")) - .then(() => this.app.analytics.initialize()) - .then(() => this.app.gameAnalytics.initialize()) - .then(() => this.setStatus("Initializing local storage")) .then(() => { const wrapper = this.app.platformWrapper; @@ -95,6 +91,10 @@ export class PreloadState extends GameState { return this.app.storage.initialize(); }) + .then(() => this.setStatus("Initializing libraries")) + .then(() => this.app.analytics.initialize()) + .then(() => this.app.gameAnalytics.initialize()) + .then(() => this.setStatus("Initializing settings")) .then(() => { return this.app.settings.initialize();
" + err + ); + return; + } + + this.app.savegameMgr.importSavegame(realContent).then( + () => { + closeLoader(); + this.dialogs.showWarning("Imported", "Your savegame has been imported."); + + this.renderSavegames(); + }, + err => { + closeLoader(); + this.dialogs.showWarning( + "Import error", + "Failed to import savegame. Please check the console output." + ); + } + ); + }); + reader.addEventListener("error", error => { + console.error(error); + alert("Failed to read file: " + error); + }); + reader.readAsText(file, "utf-8"); + }); + } + }; + input.click(); + } + onBackButton() { this.app.platformWrapper.exitApp(); } @@ -54,8 +154,13 @@ export class MainMenuState extends GameState { alert("Error while loading game: " + payload.loadError); } + this.dialogs = new HUDModalDialogs(null, this.app); + const dialogsElement = document.body.querySelector(".modalDialogParent"); + this.dialogs.initializeToElement(dialogsElement); + const qs = this.htmlElement.querySelector.bind(this.htmlElement); this.trackClicks(qs(".mainContainer .playButton"), this.onPlayButtonClicked); + this.trackClicks(qs(".mainContainer .importButton"), this.requestImportSavegame); if (G_IS_DEV && globalConfig.debug.fastGameEnter) { this.onPlayButtonClicked(); @@ -76,6 +181,10 @@ export class MainMenuState extends GameState { } renderSavegames() { + const oldContainer = this.htmlElement.querySelector(".mainContainer .savegames"); + if (oldContainer) { + oldContainer.remove(); + } const games = this.app.savegameMgr.getSavegamesMetaData(); if (games.length > 0) { const parent = makeDiv(this.htmlElement.querySelector(".mainContainer"), null, ["savegames"]); @@ -91,6 +200,10 @@ export class MainMenuState extends GameState { formatSecondsToTimeAgo((new Date().getTime() - games[i].lastUpdate) / 1000.0) ); + const deleteButton = document.createElement("button"); + deleteButton.classList.add("styledButton", "deleteGame"); + elem.appendChild(deleteButton); + const downloadButton = document.createElement("button"); downloadButton.classList.add("styledButton", "downloadGame"); elem.appendChild(downloadButton); @@ -99,6 +212,7 @@ export class MainMenuState extends GameState { resumeBtn.classList.add("styledButton", "resumeGame"); elem.appendChild(resumeBtn); + this.trackClicks(deleteButton, () => this.deleteGame(games[i])); this.trackClicks(downloadButton, () => this.downloadGame(games[i])); this.trackClicks(resumeBtn, () => this.resumeGame(games[i])); } @@ -117,6 +231,28 @@ export class MainMenuState extends GameState { }); } + /** + * @param {object} game + */ + deleteGame(game) { + const signals = this.dialogs.showWarning( + "Confirm Deletion", + "Are you sure you want to delete the game?", + ["delete:bad", "cancel:good"] + ); + + signals.delete.add(() => { + this.app.savegameMgr.deleteSavegame(game).then( + () => { + this.renderSavegames(); + }, + err => { + this.dialogs.showWarning("Failed to delete", "Error: " + err); + } + ); + }); + } + /** * @param {object} game */ @@ -138,6 +274,6 @@ export class MainMenuState extends GameState { } onLeave() { - // this.dialogs.cleanup(); + this.dialogs.cleanup(); } } diff --git a/src/js/states/preload.js b/src/js/states/preload.js index 6e885b15..b5857707 100644 --- a/src/js/states/preload.js +++ b/src/js/states/preload.js @@ -67,10 +67,6 @@ export class PreloadState extends GameState { .then(() => this.setStatus("Creating platform wrapper")) .then(() => this.app.platformWrapper.initialize()) - .then(() => this.setStatus("Initializing libraries")) - .then(() => this.app.analytics.initialize()) - .then(() => this.app.gameAnalytics.initialize()) - .then(() => this.setStatus("Initializing local storage")) .then(() => { const wrapper = this.app.platformWrapper; @@ -95,6 +91,10 @@ export class PreloadState extends GameState { return this.app.storage.initialize(); }) + .then(() => this.setStatus("Initializing libraries")) + .then(() => this.app.analytics.initialize()) + .then(() => this.app.gameAnalytics.initialize()) + .then(() => this.setStatus("Initializing settings")) .then(() => { return this.app.settings.initialize();