From 4b37150ee08df5673601997e6d1a7a193ffaf59a Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Mon, 16 Mar 2020 16:42:36 +0300 Subject: [PATCH] Improve the song loading screen error message --- public/src/css/view.css | 1 + public/src/js/controller.js | 4 +- public/src/js/loadsong.js | 130 +++++++++++++++++++++--------------- public/src/js/scoresheet.js | 6 +- public/src/js/songselect.js | 57 +++++++++++----- public/src/js/strings.js | 4 ++ 6 files changed, 126 insertions(+), 76 deletions(-) diff --git a/public/src/css/view.css b/public/src/css/view.css index 13dbefd..da0f13c 100644 --- a/public/src/css/view.css +++ b/public/src/css/view.css @@ -119,6 +119,7 @@ kbd{ background: #fff; border: 1px solid #a9a9a9; user-select: all; + box-sizing: border-box; } .text-warn{ color: #d00; diff --git a/public/src/js/controller.js b/public/src/js/controller.js index ba383e2..7c93cce 100644 --- a/public/src/js/controller.js +++ b/public/src/js/controller.js @@ -207,14 +207,14 @@ class Controller{ displayScore(score, notPlayed, bigNote){ this.view.displayScore(score, notPlayed, bigNote) } - songSelection(fadeIn, scoreSaveFailed){ + songSelection(fadeIn, showWarning){ if(!fadeIn){ this.clean() } if(this.calibrationMode){ new SettingsView(this.touchEnabled, false, null, "latency") }else{ - new SongSelect(false, fadeIn, this.touchEnabled, null, scoreSaveFailed) + new SongSelect(false, fadeIn, this.touchEnabled, null, showWarning) } } restartSong(){ diff --git a/public/src/js/loadsong.js b/public/src/js/loadsong.js index 4b42555..033c405 100644 --- a/public/src/js/loadsong.js +++ b/public/src/js/loadsong.js @@ -34,7 +34,7 @@ class LoadSong{ run(){ var song = this.selectedSong var id = song.folder - var promises = [] + this.promises = [] if(song.folder !== "calibration"){ assets.sounds["v_start"].play() var songObj = assets.songs.find(song => song.id === id) @@ -92,9 +92,9 @@ class LoadSong{ img.crossOrigin = "Anonymous" } let promise = pageEvents.load(img) - promises.push(promise.then(() => { + this.addPromise(promise.then(() => { return this.scaleImg(img, filename, prefix, force) - })) + }), songObj.music ? filename + ".png" : skinBase + filename + ".png") if(songObj.music){ img.src = URL.createObjectURL(song.songSkin[filename + ".png"]) }else{ @@ -102,14 +102,15 @@ class LoadSong{ } } } - promises.push(this.loadSongBg(id)) + this.loadSongBg(id) - promises.push(new Promise((resolve, reject) => { + var url = gameConfig.songs_baseurl + id + "/main.mp3" + this.addPromise(new Promise((resolve, reject) => { if(songObj.sound){ songObj.sound.gain = snd.musicGain resolve() }else if(!songObj.music){ - snd.musicGain.load(gameConfig.songs_baseurl + id + "/main.mp3").then(sound => { + snd.musicGain.load(url).then(sound => { songObj.sound = sound resolve() }, reject) @@ -121,15 +122,15 @@ class LoadSong{ }else{ resolve() } - })) + }), songObj.music ? songObj.music.webkitRelativePath : url) if(songObj.chart){ if(songObj.chart === "blank"){ this.songData = "" }else{ var reader = new FileReader() - promises.push(pageEvents.load(reader).then(event => { + this.addPromise(pageEvents.load(reader).then(event => { this.songData = event.target.result.replace(/\0/g, "").split("\n") - })) + }), songObj.chart.webkitRelativePath) if(song.type === "tja"){ reader.readAsText(songObj.chart, "sjis") }else{ @@ -137,68 +138,88 @@ class LoadSong{ } } }else{ - promises.push(loader.ajax(this.getSongPath(song)).then(data => { + var url = this.getSongPath(song) + this.addPromise(loader.ajax(url).then(data => { this.songData = data.replace(/\0/g, "").split("\n") - })) + }), url) } if(this.touchEnabled && !assets.image["touch_drum"]){ let img = document.createElement("img") if(this.imgScale !== 1){ img.crossOrigin = "Anonymous" } - promises.push(pageEvents.load(img).then(() => { + var url = gameConfig.assets_baseurl + "img/touch_drum.png" + this.addPromise(pageEvents.load(img).then(() => { return this.scaleImg(img, "touch_drum", "") - })) - img.src = gameConfig.assets_baseurl + "img/touch_drum.png" + }), url) + img.src = url } - Promise.all(promises).then(() => { - this.setupMultiplayer() - }, error => { - if(Array.isArray(error) && error[1] instanceof HTMLElement){ - error = error[0] + ": " + error[1].outerHTML + Promise.all(this.promises).then(() => { + if(!this.error){ + this.setupMultiplayer() } - console.error(error) - pageEvents.send("load-song-error", error) - errorMessage(new Error(error).stack) - alert(strings.errorOccured) }) } + addPromise(promise, url){ + this.promises.push(promise.catch(response => { + this.errorMsg(response, url) + return Promise.resolve() + })) + } + errorMsg(error, url){ + if(!this.error){ + if(url){ + error = (Array.isArray(error) ? error[0] + ": " : (error ? error + ": " : "")) + url + } + pageEvents.send("load-song-error", error) + errorMessage(new Error(error).stack) + var title = this.selectedSong.title + if(title !== this.selectedSong.originalTitle){ + title += " (" + this.selectedSong.originalTitle + ")" + } + this.clean() + new SongSelect(false, false, this.touchEnabled, null, { + name: "loadSongError", + title: title, + id: this.selectedSong.folder, + error: error + }) + } + this.error = true + } loadSongBg(){ - return new Promise((resolve, reject) => { - var promises = [] - var filenames = [] - if(this.selectedSong.songBg !== null){ - filenames.push("bg_song_" + this.selectedSong.songBg) + var filenames = [] + if(this.selectedSong.songBg !== null){ + filenames.push("bg_song_" + this.selectedSong.songBg) + } + if(this.selectedSong.donBg !== null){ + filenames.push("bg_don_" + this.selectedSong.donBg) + if(this.multiplayer){ + filenames.push("bg_don2_" + this.selectedSong.donBg) } - if(this.selectedSong.donBg !== null){ - filenames.push("bg_don_" + this.selectedSong.donBg) - if(this.multiplayer){ - filenames.push("bg_don2_" + this.selectedSong.donBg) - } - } - if(this.selectedSong.songStage !== null){ - filenames.push("bg_stage_" + this.selectedSong.songStage) - } - for(var i = 0; i < filenames.length; i++){ - var filename = filenames[i] - var stage = filename.startsWith("bg_stage_") - for(var letter = 0; letter < (stage ? 1 : 2); letter++){ - let filenameAb = filenames[i] + (stage ? "" : (letter === 0 ? "a" : "b")) - if(!(filenameAb in assets.image)){ - let img = document.createElement("img") - let force = filenameAb.startsWith("bg_song_") && this.touchEnabled - if(this.imgScale !== 1 || force){ - img.crossOrigin = "Anonymous" - } - promises.push(pageEvents.load(img).then(() => { - return this.scaleImg(img, filenameAb, "", force) - })) - img.src = gameConfig.assets_baseurl + "img/" + filenameAb + ".png" + } + if(this.selectedSong.songStage !== null){ + filenames.push("bg_stage_" + this.selectedSong.songStage) + } + for(var i = 0; i < filenames.length; i++){ + var filename = filenames[i] + var stage = filename.startsWith("bg_stage_") + for(var letter = 0; letter < (stage ? 1 : 2); letter++){ + let filenameAb = filenames[i] + (stage ? "" : (letter === 0 ? "a" : "b")) + if(!(filenameAb in assets.image)){ + let img = document.createElement("img") + let force = filenameAb.startsWith("bg_song_") && this.touchEnabled + if(this.imgScale !== 1 || force){ + img.crossOrigin = "Anonymous" } + var url = gameConfig.assets_baseurl + "img/" + filenameAb + ".png" + this.addPromise(pageEvents.load(img).then(() => { + return this.scaleImg(img, filenameAb, "", force) + }), url) + img.src = url } } - Promise.all(promises).then(resolve, reject) - }) + } } scaleImg(img, filename, prefix, force){ return new Promise((resolve, reject) => { @@ -333,6 +354,7 @@ class LoadSong{ pageEvents.send("load-song-cancel") } clean(){ + delete this.promises pageEvents.remove(p2, "message") if(this.cancelButton){ pageEvents.remove(this.cancelButton, ["mousedown", "touchstart"]) diff --git a/public/src/js/scoresheet.js b/public/src/js/scoresheet.js index 265414e..2a2dd81 100644 --- a/public/src/js/scoresheet.js +++ b/public/src/js/scoresheet.js @@ -864,7 +864,7 @@ class Scoresheet{ if(elapsed >= 1000){ this.clean() - this.controller.songSelection(true, this.scoreSaveFailed) + this.controller.songSelection(true, this.showWarning) } } @@ -932,12 +932,12 @@ class Scoresheet{ delete this.resultsObj.difficulty delete this.resultsObj.gauge scoreStorage.add(hash, difficulty, this.resultsObj, true, title).catch(() => { - this.scoreSaveFailed = true + this.showWarning = {name: "scoreSaveFailed"} }) }else if(oldScore && (crown === "gold" && oldScore.crown !== "gold" || crown && !oldScore.crown)){ oldScore.crown = crown scoreStorage.add(hash, difficulty, oldScore, true, title).catch(() => { - this.scoreSaveFailed = true + this.showWarning = {name: "scoreSaveFailed"} }) } } diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 11d94fd..78e9659 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -1,5 +1,5 @@ class SongSelect{ - constructor(fromTutorial, fadeIn, touchEnabled, songId, scoreSaveFailed){ + constructor(fromTutorial, fadeIn, touchEnabled, songId, showWarning){ this.touchEnabled = touchEnabled loader.changePage("songselect", false) @@ -167,7 +167,8 @@ class SongSelect{ category: strings.random }) } - if(scoreSaveFailed){ + this.showWarning = showWarning + if(showWarning && showWarning.name === "scoreSaveFailed"){ scoreStorage.scoreSaveFailed = true } this.songs.push({ @@ -383,10 +384,11 @@ class SongSelect{ return } var shift = event ? event.shiftKey : this.pressedKeys["shift"] - if(this.state.scoreSaveFailed){ + if(this.state.showWarning){ if(name === "confirm"){ this.playSound("se_don") - this.state.scoreSaveFailed = false + this.state.showWarning = false + this.showWarning = false } }else if(this.state.screen === "song"){ if(name === "confirm"){ @@ -462,10 +464,11 @@ class SongSelect{ var ctrl = false var touch = true } - if(this.state.scoreSaveFailed){ + if(this.state.showWarning){ if(408 < mouse.x && mouse.x < 872 && 470 < mouse.y && mouse.y < 550){ this.playSound("se_don") - this.state.scoreSaveFailed = false + this.state.showWarning = false + this.showWarning = false } }else if(this.state.screen === "song"){ if(20 < mouse.y && mouse.y < 90 && 410 < mouse.x && mouse.x < 880 && (mouse.x < 540 || mouse.x > 750)){ @@ -522,9 +525,9 @@ class SongSelect{ mouseMove(event){ var mouse = this.mouseOffset(event.offsetX, event.offsetY) var moveTo = null - if(this.state.scoreSaveFailed){ + if(this.state.showWarning){ if(408 < mouse.x && mouse.x < 872 && 470 < mouse.y && mouse.y < 550){ - moveTo = "scoreSaveFailed" + moveTo = "showWarning" } }else if(this.state.screen === "song"){ if(20 < mouse.y && mouse.y < 90 && 410 < mouse.x && mouse.x < 880 && (mouse.x < 540 || mouse.x > 750)){ @@ -1019,12 +1022,17 @@ class SongSelect{ } } - if(screen === "song" && scoreStorage.scoreSaveFailed && !p2.session){ + if(screen === "song" && (this.showWarning || scoreStorage.scoreSaveFailed) && !p2.session){ + if(!this.showWarning){ + this.showWarning = {name: "scoreSaveFailed"} + } if(this.bgmEnabled){ this.playBgm(false) } - scoreStorage.scoreSaveFailed = false - this.state.scoreSaveFailed = true + if(this.showWarning.name === "scoreSaveFailed"){ + scoreStorage.scoreSaveFailed = false + } + this.state.showWarning = true this.state.locked = true this.playSound("se_pause") } @@ -2130,7 +2138,7 @@ class SongSelect{ }) } - if(this.state.scoreSaveFailed){ + if(this.state.showWarning){ if(this.preview){ this.endPreview() } @@ -2164,9 +2172,24 @@ class SongSelect{ dx: 68, dy: 11 }) + if(this.showWarning.name === "scoreSaveFailed"){ + var text = strings.scoreSaveFailed + }else if(this.showWarning.name === "loadSongError"){ + var text = [] + var textIndex = 0 + var subText = [this.showWarning.title, this.showWarning.id, this.showWarning.error] + var textParts = strings.loadSongError.split("%s") + textParts.forEach((textPart, i) => { + if(i !== 0){ + text.push(subText[textIndex++]) + } + text.push(textPart) + }) + text = text.join("") + } this.draw.wrappingText({ ctx: ctx, - text: strings.scoreSaveFailed, + text: text, fontSize: 30, fontFamily: this.font, x: 300, @@ -2176,7 +2199,7 @@ class SongSelect{ lineHeight: 35, fill: "#000", verticalAlign: "middle", - textAlign: "center", + textAlign: "center" }) var _x = 640 @@ -2211,7 +2234,7 @@ class SongSelect{ }, layers) var highlight = 1 - if(this.state.moveHover === "scoreSaveFailed"){ + if(this.state.moveHover === "showWarning"){ highlight = 2 } if(highlight){ @@ -2330,7 +2353,7 @@ class SongSelect{ } startPreview(loadOnly){ - if(!loadOnly && this.state && this.state.scoreSaveFailed){ + if(!loadOnly && this.state && this.state.showWarning){ return } var currentSong = this.songs[this.selectedSong] @@ -2408,7 +2431,7 @@ class SongSelect{ } } playBgm(enabled){ - if(enabled && this.state && this.state.scoreSaveFailed){ + if(enabled && this.state && this.state.showWarning){ return } if(enabled && !this.bgmEnabled){ diff --git a/public/src/js/strings.js b/public/src/js/strings.js index 957b4aa..8eae935 100644 --- a/public/src/js/strings.js +++ b/public/src/js/strings.js @@ -266,6 +266,10 @@ var translations = { ja: null, en: "Could not connect to the server, your score has not been saved.\n\nPlease log in or refresh the page to try saving the score again." }, + loadSongError: { + ja: null, + en: "Could not load song %s with id %s.\n\n%s" + }, loading: { ja: "ロード中...", en: "Loading...",