Fix: Add robust leaderboard submission fallback and fix search.js crash
This commit is contained in:
@@ -221,6 +221,33 @@ class Scoresheet {
|
|||||||
if (this.leaderboardSubmitted) {
|
if (this.leaderboardSubmitted) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fallback: This is CRITICAL for cases where saveScore() failed or was skipped
|
||||||
|
if (!this.leaderboardData) {
|
||||||
|
console.warn("Leaderboard data missing, attempting to reconstruct...")
|
||||||
|
var song = this.controller.selectedSong
|
||||||
|
var results = this.resultsObj
|
||||||
|
|
||||||
|
if (song && results) {
|
||||||
|
var songId = song.id || song.hash
|
||||||
|
|
||||||
|
if (songId) {
|
||||||
|
this.leaderboardData = {
|
||||||
|
songId: songId,
|
||||||
|
difficulty: results.difficulty,
|
||||||
|
scoreObj: Object.assign({}, results)
|
||||||
|
}
|
||||||
|
// Clean up scoreObj
|
||||||
|
if (this.leaderboardData.scoreObj) {
|
||||||
|
delete this.leaderboardData.scoreObj.title
|
||||||
|
delete this.leaderboardData.scoreObj.difficulty
|
||||||
|
delete this.leaderboardData.scoreObj.gauge
|
||||||
|
}
|
||||||
|
console.log("Leaderboard data reconstructed:", this.leaderboardData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.leaderboardData || !this.leaderboardData.songId) {
|
if (!this.leaderboardData || !this.leaderboardData.songId) {
|
||||||
this.showLeaderboardNotification("no_song_id")
|
this.showLeaderboardNotification("no_song_id")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
class Search{
|
class Search {
|
||||||
constructor(...args){
|
constructor(...args) {
|
||||||
this.init(...args)
|
this.init(...args)
|
||||||
}
|
}
|
||||||
init(songSelect){
|
init(songSelect) {
|
||||||
this.songSelect = songSelect
|
this.songSelect = songSelect
|
||||||
this.opened = false
|
this.opened = false
|
||||||
this.enabled = true
|
this.enabled = true
|
||||||
|
|
||||||
this.style = document.createElement("style")
|
this.style = document.createElement("style")
|
||||||
var css = []
|
var css = []
|
||||||
for(var i in this.songSelect.songSkin){
|
for (var i in this.songSelect.songSkin) {
|
||||||
var skin = this.songSelect.songSkin[i]
|
var skin = this.songSelect.songSkin[i]
|
||||||
if("id" in skin || i === "default"){
|
if ("id" in skin || i === "default") {
|
||||||
var id = "id" in skin ? ("cat" + skin.id) : i
|
var id = "id" in skin ? ("cat" + skin.id) : i
|
||||||
|
|
||||||
css.push(loader.cssRuleset({
|
css.push(loader.cssRuleset({
|
||||||
[".song-search-" + id]: {
|
[".song-search-" + id]: {
|
||||||
"background-color": skin.background
|
"background-color": skin.background
|
||||||
@@ -33,7 +33,7 @@ class Search{
|
|||||||
loader.screen.appendChild(this.style)
|
loader.screen.appendChild(this.style)
|
||||||
}
|
}
|
||||||
|
|
||||||
normalizeString(string){
|
normalizeString(string) {
|
||||||
string = string
|
string = string
|
||||||
.replace('’', '\'').replace('“', '"').replace('”', '"')
|
.replace('’', '\'').replace('“', '"').replace('”', '"')
|
||||||
.replace('。', '.').replace(',', ',').replace('、', ',')
|
.replace('。', '.').replace(',', ',').replace('、', ',')
|
||||||
@@ -44,29 +44,29 @@ class Search{
|
|||||||
|
|
||||||
return string.normalize("NFKD").replace(/[\u0300-\u036f]/g, "")
|
return string.normalize("NFKD").replace(/[\u0300-\u036f]/g, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
perform(query){
|
perform(query) {
|
||||||
var results = []
|
var results = []
|
||||||
var filters = {}
|
var filters = {}
|
||||||
|
|
||||||
var querySplit = query.split(" ").filter(word => {
|
var querySplit = query.split(" ").filter(word => {
|
||||||
if(word.length > 0){
|
if (word.length > 0) {
|
||||||
var parts = word.toLowerCase().split(":")
|
var parts = word.toLowerCase().split(":")
|
||||||
if(parts.length > 1){
|
if (parts.length > 1) {
|
||||||
switch(parts[0]){
|
switch (parts[0]) {
|
||||||
case "easy":
|
case "easy":
|
||||||
case "normal":
|
case "normal":
|
||||||
case "hard":
|
case "hard":
|
||||||
case "oni":
|
case "oni":
|
||||||
case "ura":
|
case "ura":
|
||||||
var range = this.parseRange(parts[1])
|
var range = this.parseRange(parts[1])
|
||||||
if(range){
|
if (range) {
|
||||||
filters[parts[0]] = range
|
filters[parts[0]] = range
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "extreme":
|
case "extreme":
|
||||||
var range = this.parseRange(parts[1])
|
var range = this.parseRange(parts[1])
|
||||||
if(range){
|
if (range) {
|
||||||
filters.oni = this.parseRange(parts[1])
|
filters.oni = this.parseRange(parts[1])
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
@@ -91,175 +91,175 @@ class Search{
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|
||||||
query = this.normalizeString(querySplit.join(" ").trim())
|
query = this.normalizeString(querySplit.join(" ").trim())
|
||||||
|
|
||||||
var totalFilters = Object.keys(filters).length
|
var totalFilters = Object.keys(filters).length
|
||||||
var random = false
|
var random = false
|
||||||
var allResults = false
|
var allResults = false
|
||||||
for(var i = 0; i < assets.songs.length; i++){
|
for (var i = 0; i < assets.songs.length; i++) {
|
||||||
var song = assets.songs[i]
|
var song = assets.songs[i]
|
||||||
var passedFilters = 0
|
var passedFilters = 0
|
||||||
|
|
||||||
Object.keys(filters).forEach(filter => {
|
Object.keys(filters).forEach(filter => {
|
||||||
var value = filters[filter]
|
var value = filters[filter]
|
||||||
switch(filter){
|
switch (filter) {
|
||||||
case "easy":
|
case "easy":
|
||||||
case "normal":
|
case "normal":
|
||||||
case "hard":
|
case "hard":
|
||||||
case "oni":
|
case "oni":
|
||||||
case "ura":
|
case "ura":
|
||||||
if(song.courses[filter] && song.courses[filter].stars >= value.min && song.courses[filter].stars <= value.max){
|
if (song.courses[filter] && song.courses[filter].stars >= value.min && song.courses[filter].stars <= value.max) {
|
||||||
passedFilters++
|
passedFilters++
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "clear":
|
case "clear":
|
||||||
case "silver":
|
case "silver":
|
||||||
case "gold":
|
case "gold":
|
||||||
if(value === "any"){
|
if (value === "any") {
|
||||||
var score = scoreStorage.scores[song.hash]
|
var score = scoreStorage.scores[song.hash]
|
||||||
scoreStorage.difficulty.forEach(difficulty => {
|
scoreStorage.difficulty.forEach(difficulty => {
|
||||||
if(score && score[difficulty] && score[difficulty].crown && (filter === "clear" || score[difficulty].crown === filter)){
|
if (score && score[difficulty] && score[difficulty].crown && (filter === "clear" || score[difficulty].crown === filter)) {
|
||||||
passedFilters++
|
passedFilters++
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
var score = scoreStorage.scores[song.hash]
|
var score = scoreStorage.scores[song.hash]
|
||||||
if(score && score[value] && score[value].crown && (filter === "clear" || score[value].crown === filter)){
|
if (score && score[value] && score[value].crown && (filter === "clear" || score[value].crown === filter)) {
|
||||||
passedFilters++
|
passedFilters++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "played":
|
case "played":
|
||||||
var score = scoreStorage.scores[song.hash]
|
var score = scoreStorage.scores[song.hash]
|
||||||
if((value === "yes" && score) || (value === "no" && !score)){
|
if ((value === "yes" && score) || (value === "no" && !score)) {
|
||||||
passedFilters++
|
passedFilters++
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "lyrics":
|
case "lyrics":
|
||||||
if((value === "yes" && song.lyrics) || (value === "no" && !song.lyrics)){
|
if ((value === "yes" && song.lyrics) || (value === "no" && !song.lyrics)) {
|
||||||
passedFilters++
|
passedFilters++
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "creative":
|
case "creative":
|
||||||
if((value === "yes" && song.maker) || (value === "no" && !song.maker)){
|
if ((value === "yes" && song.maker) || (value === "no" && !song.maker)) {
|
||||||
passedFilters++
|
passedFilters++
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "maker":
|
case "maker":
|
||||||
if(song.maker && song.maker.name.toLowerCase().includes(value.toLowerCase())){
|
if (song.maker && song.maker.name.toLowerCase().includes(value.toLowerCase())) {
|
||||||
passedFilters++
|
passedFilters++
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "genre":
|
case "genre":
|
||||||
var cat = assets.categories.find(cat => cat.id === song.category_id)
|
var cat = assets.categories.find(cat => cat.id === song.category_id)
|
||||||
var aliases = cat.aliases ? cat.aliases.concat([cat.title]) : [cat.title]
|
var aliases = cat.aliases ? cat.aliases.concat([cat.title]) : [cat.title]
|
||||||
|
|
||||||
if(aliases.find(alias => alias.toLowerCase() === value.toLowerCase())){
|
if (aliases.find(alias => alias.toLowerCase() === value.toLowerCase())) {
|
||||||
passedFilters++
|
passedFilters++
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "diverge":
|
case "diverge":
|
||||||
var branch = Object.values(song.courses).find(course => course && course.branch)
|
var branch = Object.values(song.courses).find(course => course && course.branch)
|
||||||
if((value === "yes" && branch) || (value === "no" && !branch)){
|
if ((value === "yes" && branch) || (value === "no" && !branch)) {
|
||||||
passedFilters++
|
passedFilters++
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "random":
|
case "random":
|
||||||
if(value === "yes" || value === "no"){
|
if (value === "yes" || value === "no") {
|
||||||
random = value === "yes"
|
random = value === "yes"
|
||||||
passedFilters++
|
passedFilters++
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "all":
|
case "all":
|
||||||
if(value === "yes" || value === "no"){
|
if (value === "yes" || value === "no") {
|
||||||
allResults = value === "yes"
|
allResults = value === "yes"
|
||||||
passedFilters++
|
passedFilters++
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if(passedFilters === totalFilters){
|
if (passedFilters === totalFilters) {
|
||||||
results.push(song)
|
results.push(song)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxResults = allResults ? Infinity : (totalFilters > 0 && !query ? 100 : 50)
|
var maxResults = allResults ? Infinity : (totalFilters > 0 && !query ? 100 : 50)
|
||||||
|
|
||||||
if(query){
|
if (query) {
|
||||||
results = fuzzysort.go(query, results, {
|
results = fuzzysort.go(query, results, {
|
||||||
keys: ["titlePrepared", "subtitlePrepared"],
|
keys: ["titlePrepared", "subtitlePrepared"],
|
||||||
allowTypo: true,
|
allowTypo: true,
|
||||||
limit: maxResults,
|
limit: maxResults,
|
||||||
scoreFn: a => {
|
scoreFn: a => {
|
||||||
if(a[0]){
|
if (a[0]) {
|
||||||
var score0 = a[0].score
|
var score0 = a[0].score
|
||||||
a[0].ranges = this.indexesToRanges(a[0].indexes)
|
a[0].ranges = this.indexesToRanges(a[0].indexes)
|
||||||
if(a[0].indexes.length > 1){
|
if (a[0].indexes.length > 1) {
|
||||||
var rangeAmount = a[0].ranges.length
|
var rangeAmount = a[0].ranges.length
|
||||||
var lastIdx = -3
|
var lastIdx = -3
|
||||||
a[0].ranges.forEach(range => {
|
a[0].ranges.forEach(range => {
|
||||||
if(range[0] - lastIdx <= 2){
|
if (range[0] - lastIdx <= 2) {
|
||||||
rangeAmount--
|
rangeAmount--
|
||||||
score0 -= 1000
|
score0 -= 1000
|
||||||
}
|
}
|
||||||
lastIdx = range[1]
|
lastIdx = range[1]
|
||||||
})
|
})
|
||||||
var index = a[0].target.toLowerCase().indexOf(query)
|
var index = a[0].target.toLowerCase().indexOf(query)
|
||||||
if(index !== -1){
|
if (index !== -1) {
|
||||||
a[0].ranges = [[index, index + query.length - 1]]
|
a[0].ranges = [[index, index + query.length - 1]]
|
||||||
}else if(rangeAmount > a[0].indexes.length / 2){
|
} else if (rangeAmount > a[0].indexes.length / 2) {
|
||||||
score0 = -Infinity
|
score0 = -Infinity
|
||||||
a[0].ranges = null
|
a[0].ranges = null
|
||||||
}else if(rangeAmount !== 1){
|
} else if (rangeAmount !== 1) {
|
||||||
score0 -= 9000
|
score0 -= 9000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(a[1]){
|
if (a[1]) {
|
||||||
var score1 = a[1].score - 1000
|
var score1 = a[1].score - 1000
|
||||||
a[1].ranges = this.indexesToRanges(a[1].indexes)
|
a[1].ranges = this.indexesToRanges(a[1].indexes)
|
||||||
if(a[1].indexes.length > 1){
|
if (a[1].indexes.length > 1) {
|
||||||
var rangeAmount = a[1].ranges.length
|
var rangeAmount = a[1].ranges.length
|
||||||
var lastIdx = -3
|
var lastIdx = -3
|
||||||
a[1].ranges.forEach(range => {
|
a[1].ranges.forEach(range => {
|
||||||
if(range[0] - lastIdx <= 2){
|
if (range[0] - lastIdx <= 2) {
|
||||||
rangeAmount--
|
rangeAmount--
|
||||||
score1 -= 1000
|
score1 -= 1000
|
||||||
}
|
}
|
||||||
lastIdx = range[1]
|
lastIdx = range[1]
|
||||||
})
|
})
|
||||||
var index = a[1].target.indexOf(query)
|
var index = a[1].target.indexOf(query)
|
||||||
if(index !== -1){
|
if (index !== -1) {
|
||||||
a[1].ranges = [[index, index + query.length - 1]]
|
a[1].ranges = [[index, index + query.length - 1]]
|
||||||
}else if(rangeAmount > a[1].indexes.length / 2){
|
} else if (rangeAmount > a[1].indexes.length / 2) {
|
||||||
score1 = -Infinity
|
score1 = -Infinity
|
||||||
a[1].ranges = null
|
a[1].ranges = null
|
||||||
}else if(rangeAmount !== 1){
|
} else if (rangeAmount !== 1) {
|
||||||
score1 -= 9000
|
score1 -= 9000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(random){
|
if (random) {
|
||||||
var rand = Math.random() * -9000
|
var rand = Math.random() * -9000
|
||||||
if(score0 !== -Infinity){
|
if (score0 !== -Infinity) {
|
||||||
score0 = rand
|
score0 = rand
|
||||||
}
|
}
|
||||||
if(score1 !== -Infinity){
|
if (score1 !== -Infinity) {
|
||||||
score1 = rand
|
score1 = rand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(a[0]){
|
if (a[0]) {
|
||||||
return a[1] ? Math.max(score0, score1) : score0
|
return a[1] ? Math.max(score0, score1) : score0
|
||||||
}else{
|
} else {
|
||||||
return a[1] ? score1 : -Infinity
|
return a[1] ? score1 : -Infinity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}else{
|
} else {
|
||||||
if(random){
|
if (random) {
|
||||||
for(var i = results.length - 1; i > 0; i--){
|
for (var i = results.length - 1; i > 0; i--) {
|
||||||
var j = Math.floor(Math.random() * (i + 1))
|
var j = Math.floor(Math.random() * (i + 1))
|
||||||
var temp = results[i]
|
var temp = results[i]
|
||||||
results[i] = results[j]
|
results[i] = results[j]
|
||||||
@@ -267,53 +267,53 @@ class Search{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
results = results.slice(0, maxResults).map(result => {
|
results = results.slice(0, maxResults).map(result => {
|
||||||
return {obj: result}
|
return { obj: result }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
createResult(result, resultWidth, fontSize){
|
createResult(result, resultWidth, fontSize) {
|
||||||
var song = result.obj
|
var song = result.obj
|
||||||
var title = this.songSelect.getLocalTitle(song.title, song.title_lang)
|
var title = this.songSelect.getLocalTitle(song.title, song.title_lang)
|
||||||
var subtitle = this.songSelect.getLocalTitle(title === song.title ? song.subtitle : "", song.subtitle_lang)
|
var subtitle = this.songSelect.getLocalTitle(title === song.title ? song.subtitle : "", song.subtitle_lang)
|
||||||
|
|
||||||
var id = "default"
|
var id = "default"
|
||||||
if(song.category_id){
|
if (song.category_id) {
|
||||||
var cat = assets.categories.find(cat => cat.id === song.category_id)
|
var cat = assets.categories.find(cat => cat.id === song.category_id)
|
||||||
if(cat && "id" in cat){
|
if (cat && "id" in cat) {
|
||||||
id = "cat" + cat.id
|
id = "cat" + cat.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultDiv = document.createElement("div")
|
var resultDiv = document.createElement("div")
|
||||||
resultDiv.classList.add("song-search-result", "song-search-" + id)
|
resultDiv.classList.add("song-search-result", "song-search-" + id)
|
||||||
resultDiv.dataset.songId = song.id
|
resultDiv.dataset.songId = song.id
|
||||||
|
|
||||||
var resultInfoDiv = document.createElement("div")
|
var resultInfoDiv = document.createElement("div")
|
||||||
resultInfoDiv.classList.add("song-search-result-info")
|
resultInfoDiv.classList.add("song-search-result-info")
|
||||||
var resultInfoTitle = document.createElement("span")
|
var resultInfoTitle = document.createElement("span")
|
||||||
resultInfoTitle.classList.add("song-search-result-title")
|
resultInfoTitle.classList.add("song-search-result-title")
|
||||||
|
|
||||||
resultInfoTitle.appendChild(this.highlightResult(title, result[0]))
|
resultInfoTitle.appendChild(this.highlightResult(title, result[0]))
|
||||||
resultInfoTitle.setAttribute("alt", title)
|
resultInfoTitle.setAttribute("alt", title)
|
||||||
|
|
||||||
resultInfoDiv.appendChild(resultInfoTitle)
|
resultInfoDiv.appendChild(resultInfoTitle)
|
||||||
|
|
||||||
if(subtitle){
|
if (subtitle) {
|
||||||
resultInfoDiv.appendChild(document.createElement("br"))
|
resultInfoDiv.appendChild(document.createElement("br"))
|
||||||
var resultInfoSubtitle = document.createElement("span")
|
var resultInfoSubtitle = document.createElement("span")
|
||||||
resultInfoSubtitle.classList.add("song-search-result-subtitle")
|
resultInfoSubtitle.classList.add("song-search-result-subtitle")
|
||||||
|
|
||||||
resultInfoSubtitle.appendChild(this.highlightResult(subtitle, result[1]))
|
resultInfoSubtitle.appendChild(this.highlightResult(subtitle, result[1]))
|
||||||
resultInfoSubtitle.setAttribute("alt", subtitle)
|
resultInfoSubtitle.setAttribute("alt", subtitle)
|
||||||
|
|
||||||
resultInfoDiv.appendChild(resultInfoSubtitle)
|
resultInfoDiv.appendChild(resultInfoSubtitle)
|
||||||
}
|
}
|
||||||
|
|
||||||
resultDiv.appendChild(resultInfoDiv)
|
resultDiv.appendChild(resultInfoDiv)
|
||||||
|
|
||||||
var courses = ["easy", "normal", "hard", "oni", "ura"]
|
var courses = ["easy", "normal", "hard", "oni", "ura"]
|
||||||
courses.forEach(course => {
|
courses.forEach(course => {
|
||||||
var courseDiv = document.createElement("div")
|
var courseDiv = document.createElement("div")
|
||||||
@@ -330,40 +330,41 @@ class Search{
|
|||||||
var courseStars = document.createElement("div")
|
var courseStars = document.createElement("div")
|
||||||
courseStars.classList.add("song-search-result-stars")
|
courseStars.classList.add("song-search-result-stars")
|
||||||
courseStars.innerText = song.courses[course].stars + "\u2605"
|
courseStars.innerText = song.courses[course].stars + "\u2605"
|
||||||
|
|
||||||
courseDiv.appendChild(courseCrown)
|
courseDiv.appendChild(courseCrown)
|
||||||
courseDiv.appendChild(courseStars)
|
courseDiv.appendChild(courseStars)
|
||||||
} else {
|
} else {
|
||||||
courseDiv.classList.add("song-search-result-hidden")
|
courseDiv.classList.add("song-search-result-hidden")
|
||||||
}
|
}
|
||||||
|
|
||||||
resultDiv.appendChild(courseDiv)
|
resultDiv.appendChild(courseDiv)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.songSelect.ctx.font = (1.2 * fontSize) + "px " + strings.font
|
this.songSelect.ctx.font = (1.2 * fontSize) + "px " + strings.font
|
||||||
var titleWidth = this.songSelect.ctx.measureText(title).width
|
var titleWidth = this.songSelect.ctx.measureText(title).width
|
||||||
var titleRatio = resultWidth / titleWidth
|
var titleRatio = resultWidth / titleWidth
|
||||||
if(titleRatio < 1){
|
if (titleRatio < 1) {
|
||||||
resultInfoTitle.style.transform = "scale(" + titleRatio + ", 1)"
|
resultInfoTitle.style.transform = "scale(" + titleRatio + ", 1)"
|
||||||
}
|
}
|
||||||
if(subtitle){
|
if (subtitle) {
|
||||||
this.songSelect.ctx.font = (0.8 * 1.2 * fontSize) + "px " + strings.font
|
this.songSelect.ctx.font = (0.8 * 1.2 * fontSize) + "px " + strings.font
|
||||||
var subtitleWidth = this.songSelect.ctx.measureText(subtitle).width
|
var subtitleWidth = this.songSelect.ctx.measureText(subtitle).width
|
||||||
var subtitleRatio = resultWidth / subtitleWidth
|
var subtitleRatio = resultWidth / subtitleWidth
|
||||||
if(subtitleRatio < 1){
|
if (subtitleRatio < 1) {
|
||||||
resultInfoSubtitle.style.transform = "scale(" + subtitleRatio + ", 1)"
|
resultInfoSubtitle.style.transform = "scale(" + subtitleRatio + ", 1)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultDiv
|
return resultDiv
|
||||||
}
|
}
|
||||||
|
|
||||||
highlightResult(text, result){
|
highlightResult(text, result) {
|
||||||
|
if (text === null || text === undefined) return document.createDocumentFragment();
|
||||||
var fragment = document.createDocumentFragment()
|
var fragment = document.createDocumentFragment()
|
||||||
var ranges = (result ? result.ranges : null) || []
|
var ranges = (result ? result.ranges : null) || []
|
||||||
var lastIdx = 0
|
var lastIdx = 0
|
||||||
ranges.forEach(range => {
|
ranges.forEach(range => {
|
||||||
if(lastIdx !== range[0]){
|
if (lastIdx !== range[0]) {
|
||||||
fragment.appendChild(document.createTextNode(text.slice(lastIdx, range[0])))
|
fragment.appendChild(document.createTextNode(text.slice(lastIdx, range[0])))
|
||||||
}
|
}
|
||||||
var span = document.createElement("span")
|
var span = document.createElement("span")
|
||||||
@@ -372,91 +373,91 @@ class Search{
|
|||||||
fragment.appendChild(span)
|
fragment.appendChild(span)
|
||||||
lastIdx = range[1] + 1
|
lastIdx = range[1] + 1
|
||||||
})
|
})
|
||||||
if(text.length !== lastIdx){
|
if (text.length !== lastIdx) {
|
||||||
fragment.appendChild(document.createTextNode(text.slice(lastIdx)))
|
fragment.appendChild(document.createTextNode(text.slice(lastIdx)))
|
||||||
}
|
}
|
||||||
return fragment
|
return fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
setActive(idx){
|
setActive(idx) {
|
||||||
this.songSelect.playSound("se_ka")
|
this.songSelect.playSound("se_ka")
|
||||||
var active = this.div.querySelector(":scope .song-search-result-active")
|
var active = this.div.querySelector(":scope .song-search-result-active")
|
||||||
if(active){
|
if (active) {
|
||||||
active.classList.remove("song-search-result-active")
|
active.classList.remove("song-search-result-active")
|
||||||
}
|
}
|
||||||
|
|
||||||
if(idx === null){
|
if (idx === null) {
|
||||||
this.active = null
|
this.active = null
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var el = this.results[idx]
|
var el = this.results[idx]
|
||||||
this.input.blur()
|
this.input.blur()
|
||||||
el.classList.add("song-search-result-active")
|
el.classList.add("song-search-result-active")
|
||||||
this.scrollTo(el)
|
this.scrollTo(el)
|
||||||
|
|
||||||
this.active = idx
|
this.active = idx
|
||||||
}
|
}
|
||||||
|
|
||||||
display(fromButton=false){
|
display(fromButton = false) {
|
||||||
if(!this.enabled){
|
if (!this.enabled) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if(this.opened){
|
if (this.opened) {
|
||||||
return this.remove(true)
|
return this.remove(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.opened = true
|
this.opened = true
|
||||||
this.results = []
|
this.results = []
|
||||||
this.div = document.createElement("div")
|
this.div = document.createElement("div")
|
||||||
this.div.innerHTML = assets.pages["search"]
|
this.div.innerHTML = assets.pages["search"]
|
||||||
|
|
||||||
this.container = this.div.querySelector(":scope #song-search-container")
|
this.container = this.div.querySelector(":scope #song-search-container")
|
||||||
if(this.touchEnabled){
|
if (this.touchEnabled) {
|
||||||
this.container.classList.add("touch-enabled")
|
this.container.classList.add("touch-enabled")
|
||||||
}
|
}
|
||||||
pageEvents.add(this.container, ["mousedown", "touchstart"], this.onClick.bind(this))
|
pageEvents.add(this.container, ["mousedown", "touchstart"], this.onClick.bind(this))
|
||||||
|
|
||||||
this.input = this.div.querySelector(":scope #song-search-input")
|
this.input = this.div.querySelector(":scope #song-search-input")
|
||||||
this.input.setAttribute("placeholder", strings.search.searchInput)
|
this.input.setAttribute("placeholder", strings.search.searchInput)
|
||||||
pageEvents.add(this.input, ["input"], () => this.onInput())
|
pageEvents.add(this.input, ["input"], () => this.onInput())
|
||||||
|
|
||||||
this.songSelect.playSound("se_pause")
|
this.songSelect.playSound("se_pause")
|
||||||
loader.screen.appendChild(this.div)
|
loader.screen.appendChild(this.div)
|
||||||
this.setTip()
|
this.setTip()
|
||||||
cancelTouch = false
|
cancelTouch = false
|
||||||
noResizeRoot = true
|
noResizeRoot = true
|
||||||
if(this.songSelect.songs[this.songSelect.selectedSong].courses){
|
if (this.songSelect.songs[this.songSelect.selectedSong].courses) {
|
||||||
snd.previewGain.setVolumeMul(0.5)
|
snd.previewGain.setVolumeMul(0.5)
|
||||||
}else if(this.songSelect.bgmEnabled){
|
} else if (this.songSelect.bgmEnabled) {
|
||||||
snd.musicGain.setVolumeMul(0.5)
|
snd.musicGain.setVolumeMul(0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.input.focus()
|
this.input.focus()
|
||||||
this.input.setSelectionRange(0, this.input.value.length)
|
this.input.setSelectionRange(0, this.input.value.length)
|
||||||
}, 10)
|
}, 10)
|
||||||
|
|
||||||
var lastQuery = localStorage.getItem("lastSearchQuery")
|
var lastQuery = localStorage.getItem("lastSearchQuery")
|
||||||
if(lastQuery){
|
if (lastQuery) {
|
||||||
this.input.value = lastQuery
|
this.input.value = lastQuery
|
||||||
this.input.dispatchEvent(new Event("input", {
|
this.input.dispatchEvent(new Event("input", {
|
||||||
value: lastQuery
|
value: lastQuery
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(byUser=false){
|
remove(byUser = false) {
|
||||||
if(this.opened){
|
if (this.opened) {
|
||||||
this.opened = false
|
this.opened = false
|
||||||
if(byUser){
|
if (byUser) {
|
||||||
this.songSelect.playSound("se_cancel")
|
this.songSelect.playSound("se_cancel")
|
||||||
}
|
}
|
||||||
|
|
||||||
pageEvents.remove(this.div.querySelector(":scope #song-search-container"),
|
pageEvents.remove(this.div.querySelector(":scope #song-search-container"),
|
||||||
["mousedown", "touchstart"])
|
["mousedown", "touchstart"])
|
||||||
pageEvents.remove(this.input, ["input"])
|
pageEvents.remove(this.input, ["input"])
|
||||||
|
|
||||||
this.div.remove()
|
this.div.remove()
|
||||||
delete this.results
|
delete this.results
|
||||||
delete this.div
|
delete this.div
|
||||||
@@ -465,39 +466,39 @@ class Search{
|
|||||||
delete this.active
|
delete this.active
|
||||||
cancelTouch = true
|
cancelTouch = true
|
||||||
noResizeRoot = false
|
noResizeRoot = false
|
||||||
if(this.songSelect.songs[this.songSelect.selectedSong].courses){
|
if (this.songSelect.songs[this.songSelect.selectedSong].courses) {
|
||||||
snd.previewGain.setVolumeMul(1)
|
snd.previewGain.setVolumeMul(1)
|
||||||
}else if(this.songSelect.bgmEnabled){
|
} else if (this.songSelect.bgmEnabled) {
|
||||||
snd.musicGain.setVolumeMul(1)
|
snd.musicGain.setVolumeMul(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setTip(tip, error=false){
|
setTip(tip, error = false) {
|
||||||
if(this.tip){
|
if (this.tip) {
|
||||||
this.tip.remove()
|
this.tip.remove()
|
||||||
delete this.tip
|
delete this.tip
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!tip){
|
if (!tip) {
|
||||||
tip = strings.search.tip + " " + strings.search.tips[Math.floor(Math.random() * strings.search.tips.length)]
|
tip = strings.search.tip + " " + strings.search.tips[Math.floor(Math.random() * strings.search.tips.length)]
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultsDiv = this.div.querySelector(":scope #song-search-results")
|
var resultsDiv = this.div.querySelector(":scope #song-search-results")
|
||||||
resultsDiv.innerHTML = ""
|
resultsDiv.innerHTML = ""
|
||||||
this.results = []
|
this.results = []
|
||||||
|
|
||||||
this.tip = document.createElement("div")
|
this.tip = document.createElement("div")
|
||||||
this.tip.id = "song-search-tip"
|
this.tip.id = "song-search-tip"
|
||||||
this.tip.innerText = tip
|
this.tip.innerText = tip
|
||||||
this.div.querySelector(":scope #song-search").appendChild(this.tip)
|
this.div.querySelector(":scope #song-search").appendChild(this.tip)
|
||||||
|
|
||||||
if(error){
|
if (error) {
|
||||||
this.tip.classList.add("song-search-tip-error")
|
this.tip.classList.add("song-search-tip-error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proceed(songId){
|
proceed(songId) {
|
||||||
if (/^-?\d+$/.test(songId)) {
|
if (/^-?\d+$/.test(songId)) {
|
||||||
songId = parseInt(songId)
|
songId = parseInt(songId)
|
||||||
}
|
}
|
||||||
@@ -505,91 +506,91 @@ class Search{
|
|||||||
var song = this.songSelect.songs.find(song => song.id === songId)
|
var song = this.songSelect.songs.find(song => song.id === songId)
|
||||||
this.remove()
|
this.remove()
|
||||||
this.songSelect.playBgm(false)
|
this.songSelect.playBgm(false)
|
||||||
if(this.songSelect.previewing === "muted"){
|
if (this.songSelect.previewing === "muted") {
|
||||||
this.songSelect.previewing = null
|
this.songSelect.previewing = null
|
||||||
}
|
}
|
||||||
|
|
||||||
var songIndex = this.songSelect.songs.findIndex(song => song.id === songId)
|
var songIndex = this.songSelect.songs.findIndex(song => song.id === songId)
|
||||||
this.songSelect.setSelectedSong(songIndex)
|
this.songSelect.setSelectedSong(songIndex)
|
||||||
this.songSelect.toSelectDifficulty()
|
this.songSelect.toSelectDifficulty()
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollTo(element){
|
scrollTo(element) {
|
||||||
var parentNode = element.parentNode
|
var parentNode = element.parentNode
|
||||||
var selected = element.getBoundingClientRect()
|
var selected = element.getBoundingClientRect()
|
||||||
var parent = parentNode.getBoundingClientRect()
|
var parent = parentNode.getBoundingClientRect()
|
||||||
var scrollY = parentNode.scrollTop
|
var scrollY = parentNode.scrollTop
|
||||||
var selectedPosTop = selected.top - selected.height / 2
|
var selectedPosTop = selected.top - selected.height / 2
|
||||||
if(Math.floor(selectedPosTop) < Math.floor(parent.top)){
|
if (Math.floor(selectedPosTop) < Math.floor(parent.top)) {
|
||||||
parentNode.scrollTop += selectedPosTop - parent.top
|
parentNode.scrollTop += selectedPosTop - parent.top
|
||||||
}else{
|
} else {
|
||||||
var selectedPosBottom = selected.top + selected.height * 1.5 - parent.top
|
var selectedPosBottom = selected.top + selected.height * 1.5 - parent.top
|
||||||
if(Math.floor(selectedPosBottom) > Math.floor(parent.height)){
|
if (Math.floor(selectedPosBottom) > Math.floor(parent.height)) {
|
||||||
parentNode.scrollTop += selectedPosBottom - parent.height
|
parentNode.scrollTop += selectedPosBottom - parent.height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parseRange(string){
|
parseRange(string) {
|
||||||
var range = string.split("-")
|
var range = string.split("-")
|
||||||
if(range.length == 1){
|
if (range.length == 1) {
|
||||||
var min = parseInt(range[0]) || 0
|
var min = parseInt(range[0]) || 0
|
||||||
return min > 0 ? {min: min, max: min} : false
|
return min > 0 ? { min: min, max: min } : false
|
||||||
} else if(range.length == 2){
|
} else if (range.length == 2) {
|
||||||
var min = parseInt(range[0]) || 0
|
var min = parseInt(range[0]) || 0
|
||||||
var max = parseInt(range[1]) || 0
|
var max = parseInt(range[1]) || 0
|
||||||
return min > 0 && max > 0 ? {min: min, max: max} : false
|
return min > 0 && max > 0 ? { min: min, max: max } : false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
indexesToRanges(indexes){
|
indexesToRanges(indexes) {
|
||||||
var ranges = []
|
var ranges = []
|
||||||
var range
|
var range
|
||||||
indexes.forEach(idx => {
|
indexes.forEach(idx => {
|
||||||
if(range && range[1] === idx - 1){
|
if (range && range[1] === idx - 1) {
|
||||||
range[1] = idx
|
range[1] = idx
|
||||||
}else{
|
} else {
|
||||||
range = [idx, idx]
|
range = [idx, idx]
|
||||||
ranges.push(range)
|
ranges.push(range)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return ranges
|
return ranges
|
||||||
}
|
}
|
||||||
|
|
||||||
onInput(resize){
|
onInput(resize) {
|
||||||
var text = this.input.value
|
var text = this.input.value
|
||||||
localStorage.setItem("lastSearchQuery", text)
|
localStorage.setItem("lastSearchQuery", text)
|
||||||
text = text.toLowerCase()
|
text = text.toLowerCase()
|
||||||
|
|
||||||
if(text.length === 0){
|
if (text.length === 0) {
|
||||||
if(!resize){
|
if (!resize) {
|
||||||
this.setTip()
|
this.setTip()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var new_results = this.perform(text)
|
var new_results = this.perform(text)
|
||||||
|
|
||||||
if(new_results.length === 0){
|
if (new_results.length === 0) {
|
||||||
this.setTip(strings.search.noResults, true)
|
this.setTip(strings.search.noResults, true)
|
||||||
return
|
return
|
||||||
}else if(this.tip){
|
} else if (this.tip) {
|
||||||
this.tip.remove()
|
this.tip.remove()
|
||||||
delete this.tip
|
delete this.tip
|
||||||
}
|
}
|
||||||
|
|
||||||
var resultsDiv = this.div.querySelector(":scope #song-search-results")
|
var resultsDiv = this.div.querySelector(":scope #song-search-results")
|
||||||
resultsDiv.innerHTML = ""
|
resultsDiv.innerHTML = ""
|
||||||
this.results = []
|
this.results = []
|
||||||
|
|
||||||
var fontSize = parseFloat(getComputedStyle(this.div.querySelector(":scope #song-search")).fontSize.slice(0, -2))
|
var fontSize = parseFloat(getComputedStyle(this.div.querySelector(":scope #song-search")).fontSize.slice(0, -2))
|
||||||
var resultsWidth = parseFloat(getComputedStyle(resultsDiv).width.slice(0, -2))
|
var resultsWidth = parseFloat(getComputedStyle(resultsDiv).width.slice(0, -2))
|
||||||
var vmin = Math.min(innerWidth, lastHeight) / 100
|
var vmin = Math.min(innerWidth, lastHeight) / 100
|
||||||
var courseWidth = Math.min(3 * fontSize * 1.2, 7 * vmin)
|
var courseWidth = Math.min(3 * fontSize * 1.2, 7 * vmin)
|
||||||
var resultWidth = resultsWidth - 1.8 * fontSize - 0.8 * fontSize - (courseWidth + 0.4 * fontSize * 1.2) * 5 - 0.6 * fontSize
|
var resultWidth = resultsWidth - 1.8 * fontSize - 0.8 * fontSize - (courseWidth + 0.4 * fontSize * 1.2) * 5 - 0.6 * fontSize
|
||||||
|
|
||||||
this.songSelect.ctx.save()
|
this.songSelect.ctx.save()
|
||||||
|
|
||||||
var fragment = document.createDocumentFragment()
|
var fragment = document.createDocumentFragment()
|
||||||
new_results.forEach(result => {
|
new_results.forEach(result => {
|
||||||
var result = this.createResult(result, resultWidth, fontSize)
|
var result = this.createResult(result, resultWidth, fontSize)
|
||||||
@@ -597,78 +598,78 @@ class Search{
|
|||||||
this.results.push(result)
|
this.results.push(result)
|
||||||
})
|
})
|
||||||
resultsDiv.appendChild(fragment)
|
resultsDiv.appendChild(fragment)
|
||||||
|
|
||||||
this.songSelect.ctx.restore()
|
this.songSelect.ctx.restore()
|
||||||
}
|
}
|
||||||
|
|
||||||
onClick(e){
|
onClick(e) {
|
||||||
if((e.target.id === "song-search-container" || e.target.id === "song-search-close") && e.which === 1){
|
if ((e.target.id === "song-search-container" || e.target.id === "song-search-close") && e.which === 1) {
|
||||||
this.remove(true)
|
this.remove(true)
|
||||||
}else if(e.which === 1){
|
} else if (e.which === 1) {
|
||||||
var songEl = e.target.closest(".song-search-result")
|
var songEl = e.target.closest(".song-search-result")
|
||||||
if(songEl){
|
if (songEl) {
|
||||||
var songId = songEl.dataset.songId
|
var songId = songEl.dataset.songId
|
||||||
this.proceed(songId)
|
this.proceed(songId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keyPress(pressed, name, event, repeat, ctrl){
|
keyPress(pressed, name, event, repeat, ctrl) {
|
||||||
if(name === "back" || (event && event.keyCode && event.keyCode === 70 && ctrl)) {
|
if (name === "back" || (event && event.keyCode && event.keyCode === 70 && ctrl)) {
|
||||||
this.remove(true)
|
this.remove(true)
|
||||||
if(event){
|
if (event) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
}
|
}
|
||||||
}else if(name === "down" && this.results.length){
|
} else if (name === "down" && this.results.length) {
|
||||||
if(this.input == document.activeElement && this.results){
|
if (this.input == document.activeElement && this.results) {
|
||||||
this.setActive(0)
|
this.setActive(0)
|
||||||
}else if(this.active === this.results.length - 1){
|
} else if (this.active === this.results.length - 1) {
|
||||||
this.setActive(null)
|
this.setActive(null)
|
||||||
this.input.focus()
|
this.input.focus()
|
||||||
}else if(Number.isInteger(this.active)){
|
} else if (Number.isInteger(this.active)) {
|
||||||
this.setActive(this.active + 1)
|
this.setActive(this.active + 1)
|
||||||
}else{
|
} else {
|
||||||
this.setActive(0)
|
this.setActive(0)
|
||||||
}
|
}
|
||||||
}else if(name === "up" && this.results.length){
|
} else if (name === "up" && this.results.length) {
|
||||||
if(this.input == document.activeElement && this.results){
|
if (this.input == document.activeElement && this.results) {
|
||||||
this.setActive(this.results.length - 1)
|
this.setActive(this.results.length - 1)
|
||||||
}else if(this.active === 0){
|
} else if (this.active === 0) {
|
||||||
this.setActive(null)
|
this.setActive(null)
|
||||||
this.input.focus()
|
this.input.focus()
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.input.setSelectionRange(this.input.value.length, this.input.value.length)
|
this.input.setSelectionRange(this.input.value.length, this.input.value.length)
|
||||||
}, 0)
|
}, 0)
|
||||||
}else if(Number.isInteger(this.active)){
|
} else if (Number.isInteger(this.active)) {
|
||||||
this.setActive(this.active - 1)
|
this.setActive(this.active - 1)
|
||||||
}else{
|
} else {
|
||||||
this.setActive(this.results.length - 1)
|
this.setActive(this.results.length - 1)
|
||||||
}
|
}
|
||||||
}else if(name === "confirm"){
|
} else if (name === "confirm") {
|
||||||
if(Number.isInteger(this.active)){
|
if (Number.isInteger(this.active)) {
|
||||||
this.proceed(this.results[this.active].dataset.songId)
|
this.proceed(this.results[this.active].dataset.songId)
|
||||||
}else{
|
} else {
|
||||||
this.onInput()
|
this.onInput()
|
||||||
if(event.keyCode === 13 && this.songSelect.touchEnabled){
|
if (event.keyCode === 13 && this.songSelect.touchEnabled) {
|
||||||
this.input.blur()
|
this.input.blur()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw(){
|
redraw() {
|
||||||
if(this.opened && this.container){
|
if (this.opened && this.container) {
|
||||||
var vmin = Math.min(innerWidth, lastHeight) / 100
|
var vmin = Math.min(innerWidth, lastHeight) / 100
|
||||||
if(this.vmin !== vmin){
|
if (this.vmin !== vmin) {
|
||||||
this.container.style.setProperty("--vmin", vmin + "px")
|
this.container.style.setProperty("--vmin", vmin + "px")
|
||||||
this.vmin = vmin
|
this.vmin = vmin
|
||||||
}
|
}
|
||||||
}else{
|
} else {
|
||||||
this.vmin = null
|
this.vmin = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clean(){
|
clean() {
|
||||||
loader.screen.removeChild(this.style)
|
loader.screen.removeChild(this.style)
|
||||||
fuzzysort.cleanup()
|
fuzzysort.cleanup()
|
||||||
delete this.container
|
delete this.container
|
||||||
|
|||||||
Reference in New Issue
Block a user