diff --git a/app.py b/app.py index 76de22d..d5213b3 100644 --- a/app.py +++ b/app.py @@ -191,10 +191,10 @@ def route_admin(): @app.route('/admin/songs') @admin_required(level=50) def route_admin_songs(): - songs = db.songs.find({}) + songs = sorted(list(db.songs.find({})), key=lambda x: x['id']) categories = db.categories.find({}) user = db.users.find_one({'username': session['username']}) - return render_template('admin_songs.html', songs=list(songs), admin=user, categories=list(categories)) + return render_template('admin_songs.html', songs=songs, admin=user, categories=list(categories), config=get_config()) @app.route('/admin/songs/') @@ -210,7 +210,7 @@ def route_admin_songs_id(id): user = db.users.find_one({'username': session['username']}) return render_template('admin_song_detail.html', - song=song, categories=categories, song_skins=song_skins, makers=makers, admin=user) + song=song, categories=categories, song_skins=song_skins, makers=makers, admin=user, config=get_config()) @app.route('/admin/songs/new') @@ -219,8 +219,10 @@ def route_admin_songs_new(): categories = list(db.categories.find({})) song_skins = list(db.song_skins.find({})) makers = list(db.makers.find({})) + seq = db.seq.find_one({'name': 'songs'}) + seq_new = seq['value'] + 1 if seq else 1 - return render_template('admin_song_new.html', categories=categories, song_skins=song_skins, makers=makers) + return render_template('admin_song_new.html', categories=categories, song_skins=song_skins, makers=makers, config=get_config(), id=seq_new) @app.route('/admin/songs/new', methods=['POST']) diff --git a/public/src/css/game.css b/public/src/css/game.css index afa1c70..8168f2e 100644 --- a/public/src/css/game.css +++ b/public/src/css/game.css @@ -15,6 +15,7 @@ z-index: 1; width: 100%; height: 100%; + touch-action: none; } #touch-drum{ display: none; diff --git a/public/src/css/main.css b/public/src/css/main.css index c6e1f80..e84b410 100644 --- a/public/src/css/main.css +++ b/public/src/css/main.css @@ -55,6 +55,9 @@ white-space: nowrap; transition: background-image 0.5s; } +#song-select.unfocused{ + animation-play-state: paused; +} #song-sel-canvas{ position: absolute; right: 0; diff --git a/public/src/css/view.css b/public/src/css/view.css index 6971dac..cc55123 100644 --- a/public/src/css/view.css +++ b/public/src/css/view.css @@ -59,6 +59,9 @@ kbd{ line-height: 1.4; white-space: nowrap; } +.key-join{ + font-size: 0.6em; +} .taibtn{ display: inline-block; background: #f6ead4; diff --git a/public/src/js/browsersupport.js b/public/src/js/browsersupport.js index a4e4e75..20698eb 100644 --- a/public/src/js/browsersupport.js +++ b/public/src/js/browsersupport.js @@ -53,6 +53,9 @@ function browserSupport(){ }, "OGG or WebAssembly": function(){ return new Audio().canPlayType("audio/ogg;codecs=vorbis") || "WebAssembly" in window + }, + "KeyboardEvent.key": function(){ + return "key" in KeyboardEvent.prototype } } failedTests = [] diff --git a/public/src/js/controller.js b/public/src/js/controller.js index 3433069..9da4b1c 100644 --- a/public/src/js/controller.js +++ b/public/src/js/controller.js @@ -25,7 +25,7 @@ class Controller{ this.videoLatency = 0 if(!this.calibrationMode){ var latency = settings.getItem("latency") - if(!autoPlayEnabled){ + if(!autoPlayEnabled || this.multiplayer){ this.audioLatency = Math.round(latency.audio) || 0 } this.videoLatency = Math.round(latency.video) || 0 + this.audioLatency @@ -218,6 +218,9 @@ class Controller{ } displayResults(){ if(this.multiplayer !== 2){ + if(this.view.cursorHidden){ + this.view.canvas.style.cursor = "" + } this.scoresheet = new Scoresheet(this, this.getGlobalScore(), this.multiplayer, this.touchEnabled) } } @@ -251,15 +254,15 @@ class Controller{ var chartDiff = this.selectedSong.difficulty chart = chart[chartDiff] } - promises.push(chart.read(this.selectedSong.type === "tja" ? "sjis" : undefined).then(data => { + this.addPromise(promises, chart.read(this.selectedSong.type === "tja" ? "sjis" : undefined).then(data => { this.songData = data.replace(/\0/g, "").split("\n") return Promise.resolve() - })) + }), chart.url) } if(songObj.lyricsFile){ - promises.push(songObj.lyricsFile.read().then(result => { + this.addPromise(promises, songObj.lyricsFile.read().then(result => { songObj.lyricsData = result - }, () => Promise.resolve()), songObj.lyricsFile.path) + }, () => Promise.resolve()), songObj.lyricsFile.url) } Promise.all(promises).then(resolve) } @@ -269,6 +272,32 @@ class Controller{ }) } } + addPromise(promises, promise, url){ + promises.push(promise.catch(error => { + if(this.restartSongError){ + return + } + this.restartSongError = true + 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 + ")" + } + setTimeout(() => { + new SongSelect(false, false, this.touchEnabled, null, { + name: "loadSongError", + title: title, + id: this.selectedSong.folder, + error: error + }) + }, 500) + return Promise.reject(error) + })) + } playSound(id, time, noSnd){ if(!this.drumSounds && (id === "neiro_1_don" || id === "neiro_1_ka" || id === "se_don" || id === "se_ka")){ return diff --git a/public/src/js/customsongs.js b/public/src/js/customsongs.js index e20eb2d..2d21fa2 100644 --- a/public/src/js/customsongs.js +++ b/public/src/js/customsongs.js @@ -20,12 +20,18 @@ class CustomSongs{ this.items = [] this.linkLocalFolder = document.getElementById("link-localfolder") this.hasLocal = "webkitdirectory" in HTMLInputElement.prototype && !(/Android|iPhone|iPad/.test(navigator.userAgent)) + this.selected = -1 + if(this.hasLocal){ this.browse = document.getElementById("browse") pageEvents.add(this.browse, "change", this.browseChange.bind(this)) this.setAltText(this.linkLocalFolder, strings.customSongs.localFolder) pageEvents.add(this.linkLocalFolder, ["mousedown", "touchstart"], this.localFolder.bind(this)) this.items.push(this.linkLocalFolder) + if(this.selected === -1){ + this.linkLocalFolder.classList.add("selected") + this.selected = this.items.length - 1 + } }else{ this.linkLocalFolder.parentNode.removeChild(this.linkLocalFolder) } @@ -35,6 +41,10 @@ class CustomSongs{ this.setAltText(this.linkGdriveFolder, strings.customSongs.gdriveFolder) pageEvents.add(this.linkGdriveFolder, ["mousedown", "touchstart"], this.gdriveFolder.bind(this)) this.items.push(this.linkGdriveFolder) + if(this.selected === -1){ + this.linkGdriveFolder.classList.add("selected") + this.selected = this.items.length - 1 + } }else{ this.linkGdriveFolder.parentNode.removeChild(this.linkGdriveFolder) } @@ -43,7 +53,10 @@ class CustomSongs{ this.setAltText(this.endButton, strings.session.cancel) pageEvents.add(this.endButton, ["mousedown", "touchstart"], event => this.onEnd(event, true)) this.items.push(this.endButton) - this.selected = this.items.length - 1 + if(this.selected === -1){ + this.endButton.classList.add("selected") + this.selected = this.items.length - 1 + } this.loaderDiv = document.createElement("div") this.loaderDiv.innerHTML = assets.pages["loadsong"] diff --git a/public/src/js/gameinput.js b/public/src/js/gameinput.js index 78f7284..bacdddd 100644 --- a/public/src/js/gameinput.js +++ b/public/src/js/gameinput.js @@ -212,11 +212,6 @@ class GameInput{ } this.keyboardEvents++ } - }else{ - this.keys[name] = false - this.waitKeyupScore[name] = false - this.waitKeyupSound[name] = false - this.waitKeyupMenu[name] = false } } isWaiting(name, type){ diff --git a/public/src/js/loadsong.js b/public/src/js/loadsong.js index bcf462f..5410a6d 100644 --- a/public/src/js/loadsong.js +++ b/public/src/js/loadsong.js @@ -110,7 +110,7 @@ class LoadSong{ if(songObj.custom){ this.addPromise(song.songSkin[filename + ".png"].blob().then(blob => { img.src = URL.createObjectURL(blob) - })) + }), song.songSkin[filename + ".png"].url) }else{ img.src = skinBase + filename + ".png" } @@ -118,7 +118,7 @@ class LoadSong{ } this.loadSongBg(id) - if(songObj.sound){ + if(songObj.sound && songObj.sound.buffer){ songObj.sound.gain = snd.musicGain }else if(songObj.music !== "muted"){ this.addPromise(snd.musicGain.load(songObj.music).then(sound => { diff --git a/public/src/js/mekadon.js b/public/src/js/mekadon.js index a58247e..d8cf58d 100644 --- a/public/src/js/mekadon.js +++ b/public/src/js/mekadon.js @@ -4,6 +4,7 @@ class Mekadon{ this.game = game this.lr = false this.lastHit = -Infinity + this.delay = controller.audioLatency } play(circle){ var type = circle.type @@ -24,7 +25,7 @@ class Mekadon{ } } playAt(circle, ms, score, dai, reverse){ - var currentMs = circle.ms - this.getMS() + var currentMs = circle.ms - this.getMS() + this.delay if(ms > currentMs - 10){ return this.playNow(circle, score, dai, reverse) } diff --git a/public/src/js/p2.js b/public/src/js/p2.js index 179850a..b73690e 100644 --- a/public/src/js/p2.js +++ b/public/src/js/p2.js @@ -218,7 +218,7 @@ class P2Connection{ var type = circle.type var drumrollNotes = type === "balloon" || type === "drumroll" || type === "daiDrumroll" - if(drumrollNotes && mekadon.getMS() > circle.endTime){ + if(drumrollNotes && mekadon.getMS() > circle.endTime + mekadon.delay){ circle.played(-1, false) mekadon.game.updateCurrentCircle() } diff --git a/public/src/js/parsetja.js b/public/src/js/parsetja.js index 07a11b9..964a1d8 100644 --- a/public/src/js/parsetja.js +++ b/public/src/js/parsetja.js @@ -226,21 +226,21 @@ for (var i = 0; i < currentMeasure.length; i++){ //console.log(note_chain.length); var note = currentMeasure[i] + circleID++ + var circleObj = new Circle({ + id: circleID, + start: note.start, + type: note.type, + txt: note.txt, + speed: note.bpm * note.scroll / 60, + gogoTime: note.gogo, + endTime: note.endTime, + requiredHits: note.requiredHits, + beatMS: 60000 / note.bpm, + branch: currentBranch, + section: note.section + }) if (note.type) { - circleID++ - var circleObj = new Circle({ - id: circleID, - start: note.start, - type: note.type, - txt: note.txt, - speed: note.bpm * note.scroll / 60, - gogoTime: note.gogo, - endTime: note.endTime, - requiredHits: note.requiredHits, - beatMS: 60000 / note.bpm, - branch: currentBranch, - section: note.section - }) if (note.type === "don" || note.type === "ka" || note.type === "daiDon" || note.type === "daiKa") { note_chain.push(circleObj); } else { @@ -253,9 +253,6 @@ lastDrumroll = circleObj } - if(note.event){ - this.events.push(circleObj) - } if(note.type !== "event"){ circles.push(circleObj) } @@ -266,6 +263,9 @@ } note_chain = []; } + if(note.event){ + this.events.push(circleObj) + } if("lyricsLine" in note){ if(!this.lyrics){ this.lyrics = [] @@ -488,8 +488,9 @@ sectionBegin = false if(lastDrumroll){ if(symbol === "9"){ - insertBlankNote({ + insertNote({ endDrumroll: lastDrumroll, + gogo: gogo, bpm: bpm, scroll: scroll, section: sectionBegin @@ -514,8 +515,9 @@ break case "8": if(lastDrumroll){ - insertBlankNote({ + insertNote({ endDrumroll: lastDrumroll, + gogo: gogo, bpm: bpm, scroll: scroll, section: sectionBegin @@ -523,10 +525,7 @@ sectionBegin = false lastDrumroll = false }else{ - insertBlankNote({ - bpm: bpm, - scroll: scroll - }) + insertBlankNote() } break case ",": diff --git a/public/src/js/scoresheet.js b/public/src/js/scoresheet.js index 2a2dd81..d964560 100644 --- a/public/src/js/scoresheet.js +++ b/public/src/js/scoresheet.js @@ -236,6 +236,12 @@ class Scoresheet{ } } }else if(!document.hasFocus() && this.state.screen === "scoresShown"){ + if(this.state["countup0"]){ + this.stopSound("se_results_countup", 0) + } + if(this.state["countup1"]){ + this.stopSound("se_results_countup", 1) + } return }else{ ctx.clearRect(0, 0, winW / ratio, winH / ratio) diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 83e51e6..f775e07 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -258,13 +258,15 @@ class SongSelect{ screenMS: this.getMS(), move: 0, moveMS: 0, + mouseMoveMS: 0, ura: 0, moveHover: null, locked: true, hasPointer: false, options: 0, selLock: false, - catJump: false + catJump: false, + focused: true } this.songSelecting = { speed: 800, @@ -284,7 +286,8 @@ class SongSelect{ down: ["down"], session: ["backspace"], ctrl: ["ctrl"], - shift: ["shift"] + shift: ["shift"], + mute: ["q"] }, this.keyPress.bind(this)) this.gamepad = new Gamepad({ confirm: ["b", "start", "ls", "rs"], @@ -294,7 +297,7 @@ class SongSelect{ up: ["u", "lsu"], down: ["d", "lsd"], session: ["back"], - ctrl: ["y"], + ctrlGamepad: ["y"], shift: ["x"], jump_left: ["lb"], jump_right: ["rb"] @@ -341,6 +344,7 @@ class SongSelect{ if(name === "ctrl" || name === "shift" || !this.redrawRunning){ return } + var ctrl = this.pressedKeys["ctrl"] || this.pressedKeys["ctrlGamepad"] var shift = event ? event.shiftKey : this.pressedKeys["shift"] if(this.state.showWarning){ if(name === "confirm"){ @@ -375,6 +379,9 @@ class SongSelect{ this.categoryJump(-1) }else if(name === "jump_right" && !repeat){ this.categoryJump(1) + }else if(name === "mute" || name === "ctrlGamepad"){ + this.endPreview(true) + this.playBgm(false) } }else if(this.state.screen === "difficulty"){ if(name === "confirm"){ @@ -383,7 +390,7 @@ class SongSelect{ }else if(this.selectedDiff === 1){ this.toOptions(1) }else{ - this.toLoadSong(this.selectedDiff - this.diffOptions.length, shift, this.pressedKeys["ctrl"]) + this.toLoadSong(this.selectedDiff - this.diffOptions.length, shift, ctrl) } }else if(name === "back" || name === "session"){ this.toSongSelect() @@ -393,6 +400,9 @@ class SongSelect{ this.moveToDiff(1) }else if(this.selectedDiff === 1 && (name === "up" || name === "down")){ this.toOptions(name === "up" ? -1 : 1) + }else if(name === "mute" || name === "ctrlGamepad"){ + this.endPreview(true) + this.playBgm(false) } } } @@ -417,7 +427,9 @@ class SongSelect{ var touch = false }else{ event.preventDefault() - var mouse = this.mouseOffset(event.touches[0].pageX, event.touches[0].pageY) + var x = event.touches[0].pageX - this.canvas.offsetLeft + var y = event.touches[0].pageY - this.canvas.offsetTop + var mouse = this.mouseOffset(x, y) var shift = false var ctrl = false var touch = true @@ -472,7 +484,9 @@ class SongSelect{ if(this.state.screen === "song" && this.redrawRunning){ var currentSong = this.songs[this.selectedSong] if(currentSong.action === "customSongs"){ - var mouse = this.mouseOffset(event.changedTouches[0].pageX, event.changedTouches[0].pageY) + var x = event.changedTouches[0].pageX - this.canvas.offsetLeft + var y = event.changedTouches[0].pageY - this.canvas.offsetTop + var mouse = this.mouseOffset(x, y) var moveBy = this.songSelMouse(mouse.x, mouse.y) if(moveBy === 0){ this.toCustomSongs() @@ -499,14 +513,14 @@ class SongSelect{ }else{ var moveTo = this.songSelMouse(mouse.x, mouse.y) if(moveTo === null && this.state.moveHover === 0 && !this.songs[this.selectedSong].courses){ - this.state.moveMS = this.getMS() - this.songSelecting.speed + this.state.mouseMoveMS = this.getMS() - this.songSelecting.speed } } this.state.moveHover = moveTo }else if(this.state.screen === "difficulty"){ var moveTo = this.diffSelMouse(mouse.x, mouse.y) if(moveTo === null && this.state.moveHover === this.selectedDiff){ - this.state.moveMS = this.getMS() - 1000 + this.state.mouseMoveMS = this.getMS() - 1000 } this.state.moveHover = moveTo } @@ -953,11 +967,18 @@ class SongSelect{ this.selectableText = "" }else if(!document.hasFocus() && !p2.session){ - this.pointer(false) + if(this.state.focused){ + this.state.focused = false + this.songSelect.classList.add("unfocused") + } return }else{ ctx.clearRect(0, 0, winW / ratio, winH / ratio) } + if(!this.state.focused){ + this.state.focused = true + this.songSelect.classList.remove("unfocused") + } this.winW = winW this.winH = winH this.ratio = ratio @@ -1178,7 +1199,9 @@ class SongSelect{ selectedWidth = this.songAsset.width } }else{ - this.playBgm(!this.songs[this.selectedSong].courses) + if(this.previewing !== "muted"){ + this.playBgm(!this.songs[this.selectedSong].courses) + } this.state.locked = 0 } }else if(screen === "difficulty"){ @@ -1220,7 +1243,7 @@ class SongSelect{ this.endPreview() } }else if(screen !== "title" && screen !== "titleFadeIn" && ms > this.state.moveMS + 100){ - if(this.previewing !== this.selectedSong && "id" in this.songs[this.selectedSong]){ + if(this.previewing !== "muted" && this.previewing !== this.selectedSong && "id" in this.songs[this.selectedSong]){ this.startPreview() } } @@ -1328,7 +1351,7 @@ class SongSelect{ borderStyle: selectedSkin.border, highlight: highlight, noCrop: screen === "difficulty", - animateMS: this.state.moveMS, + animateMS: Math.max(this.state.moveMS, this.state.mouseMoveMS), cached: selectedWidth === this.songAsset.fullWidth ? 3 : (selectedWidth === this.songAsset.selectedWidth ? 2 : (selectedWidth === this.songAsset.width ? 1 : 0)), frameCache: this.songFrameCache, disabled: p2.session && currentSong.action && currentSong.action !== "random", @@ -1430,7 +1453,7 @@ class SongSelect{ w: 64, h: 304, animate: highlight === 1, - animateMS: this.state.moveMS, + animateMS: Math.max(this.state.moveMS, this.state.mouseMoveMS), opacity: highlight === 2 ? 0.8 : 1, radius: 24 }) @@ -1547,7 +1570,8 @@ class SongSelect{ var songStarsObj = (currentUra ? currentSong.courses.ura : currentSong.courses[this.difficultyId[i]]) var songStars = songStarsObj.stars var songBranch = songStarsObj.branch - var elapsedMS = this.state.screenMS > this.state.moveMS || !songSel ? this.state.screenMS : this.state.moveMS + var moveMS = Math.max(this.state.moveMS, this.state.mouseMoveMS) + var elapsedMS = this.state.screenMS > moveMS || !songSel ? this.state.screenMS : moveMS var fade = ((ms - elapsedMS) % 2000) / 2000 if(songBranch && fade > 0.25 && fade < 0.75){ this.draw.verticalText({ @@ -1616,7 +1640,7 @@ class SongSelect{ w: 64, h: 362, animate: highlight === 1, - animateMS: this.state.moveMS, + animateMS: Math.max(this.state.moveMS, this.state.mouseMoveMS), opacity: highlight === 2 ? 0.8 : 1 }) } @@ -1627,7 +1651,7 @@ class SongSelect{ var currentUra = i === 3 && (this.state.ura && !songSel || currentSong.courses.ura && songSel) if(songSel && currentUra){ drawDifficulty(ctx, i, false) - var elapsedMS = this.state.screenMS > this.state.moveMS ? this.state.screenMS : this.state.moveMS + var elapsedMS = Math.max(this.state.screenMS, this.state.moveMS, this.state.mouseMoveMS) var fade = ((ms - elapsedMS) % 4000) / 4000 var alphaFade = 0 if(fade > 0.95){ @@ -1651,6 +1675,9 @@ class SongSelect{ var _x = x + 402 + i * 100 var _y = y + 87 var currentDiff = this.selectedDiff - this.diffOptions.length + if(this.selectedDiff === 4 + this.diffOptions.length){ + currentDiff = 3 + } this.draw.diffCursor({ ctx: ctx, font: this.font, @@ -2241,7 +2268,7 @@ class SongSelect{ w: _w + 7, h: _h + 7, animate: highlight === 1, - animateMS: this.state.moveMS, + animateMS: Math.max(this.state.moveMS, this.state.mouseMoveMS), opacity: highlight === 2 ? 0.8 : 1, radius: 30 }) @@ -2273,8 +2300,8 @@ class SongSelect{ this.songSelect.style.backgroundImage = "url('" + assets.image[filename].src + "')" }else{ this.songSelect.style.backgroundImage = "url('" + assets.image["bg_genre_def"].src + "')" - } } + } drawClosedSong(config){ var ctx = config.ctx @@ -2288,7 +2315,7 @@ class SongSelect{ config.borderStyle = config.song.skin.border config.outline = config.song.skin.outline config.text = config.song.title - config.animateMS = this.state.moveMS + config.animateMS = Math.max(this.state.moveMS, this.state.mouseMoveMS) config.cached = 1 config.frameCache = this.songFrameCache config.innerContent = (x, y, w, h) => { @@ -2376,7 +2403,7 @@ class SongSelect{ var currentSong = this.songs[this.selectedSong] var id = currentSong.id var prvTime = currentSong.preview - this.endPreview(true) + this.endPreview() if("id" in currentSong){ var startLoad = this.getMS() @@ -2445,9 +2472,9 @@ class SongSelect{ snd.previewGain.setVolumeMul(volume || 1) this.preview.playLoop(delay / 1000, false, prvTime) } - endPreview(){ + endPreview(force){ this.previewId++ - this.previewing = null + this.previewing = force ? "muted" : null if(this.preview){ this.preview.stop() } diff --git a/public/src/js/strings.js b/public/src/js/strings.js index fb12ef9..8969726 100644 --- a/public/src/js/strings.js +++ b/public/src/js/strings.js @@ -506,6 +506,33 @@ var translations = { cn: "确定", tw: "確定", ko: "확인" + }, + key: { + ctrl: { + en: "CTRL" + }, + shift: { + en: "⇧ SHIFT" + }, + leftArrow: { + en: "\u2190" + }, + rightArrow: { + en: "\u2192" + }, + esc: { + en: "ESC" + }, + join: { + en: "+" + }, + or: { + ja: "または", + en: " or ", + cn: "或", + tw: "或", + ko: " 또는 " + } } }, about: { diff --git a/public/src/js/tutorial.js b/public/src/js/tutorial.js index b753ede..bb69082 100644 --- a/public/src/js/tutorial.js +++ b/public/src/js/tutorial.js @@ -36,9 +36,29 @@ class Tutorial{ parent.appendChild(document.createTextNode(text)) } insertKey(key, parent){ - var kbd = document.createElement("kbd") - kbd.innerText = key - parent.appendChild(kbd) + if(!Array.isArray(key)){ + key = [key] + } + var join = true + for(var i = 0; i < key.length; i++){ + if(key[i] === false){ + join = false + continue + } + if(i !== 0){ + if(join){ + var span = document.createElement("span") + span.classList.add("key-join") + span.innerText = strings.tutorial.key.join + parent.appendChild(span) + }else{ + parent.appendChild(document.createTextNode(strings.tutorial.key.or)) + } + } + var kbd = document.createElement("kbd") + kbd.innerText = key[i] + parent.appendChild(kbd) + } } onEnd(pressed, name){ if(pressed){ @@ -59,13 +79,21 @@ class Tutorial{ this.endButton.setAttribute("alt", strings.tutorial.ok) this.tutorialDiv.innerHTML = "" var kbdSettings = settings.getItem("keyboardSettings") - var pauseKey = "ESC" + var pauseKey = [strings.tutorial.key.esc] + if(pageEvents.kbd.indexOf("q") === -1){ + pauseKey.push(false) + pauseKey.push("Q") + } var keys = [ kbdSettings.don_l[0].toUpperCase(), kbdSettings.don_r[0].toUpperCase(), kbdSettings.ka_l[0].toUpperCase(), kbdSettings.ka_r[0].toUpperCase(), - pauseKey, "SHIFT+LEFT", "SHIFT+RIGHT", "SHIFT", "CTRL" + pauseKey, + [strings.tutorial.key.shift, strings.tutorial.key.leftArrow], + [strings.tutorial.key.shift, strings.tutorial.key.rightArrow], + strings.tutorial.key.shift, + strings.tutorial.key.ctrl ] var keyIndex = 0 strings.tutorial.basics.forEach(string => { diff --git a/public/src/views/customsongs.html b/public/src/views/customsongs.html index f7f4dcf..d5511b0 100644 --- a/public/src/views/customsongs.html +++ b/public/src/views/customsongs.html @@ -6,7 +6,7 @@ -
+
diff --git a/templates/admin.html b/templates/admin.html index 410182d..f0a8019 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -3,6 +3,7 @@ Taiko Web Admin + diff --git a/templates/admin_song_detail.html b/templates/admin_song_detail.html index 12ef1d7..17932ee 100644 --- a/templates/admin_song_detail.html +++ b/templates/admin_song_detail.html @@ -1,6 +1,6 @@ {% extends 'admin.html' %} {% block content %} -{% if song.title_lang.en %} +{% if song.title_lang.en and song.title_lang.en != song.title %}

{{ song.title_lang.en }} ({{ song.title }}) (ID: {{ song.id }})

{% else %}

{{ song.title }} (ID: {{ song.id }})

diff --git a/templates/admin_song_new.html b/templates/admin_song_new.html index aefacc4..09b1991 100644 --- a/templates/admin_song_new.html +++ b/templates/admin_song_new.html @@ -1,6 +1,6 @@ {% extends 'admin.html' %} {% block content %} -

New song

+

New song (ID: {{ id }})

{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %} @@ -9,7 +9,7 @@
- +