From b42b246a9977454ca243771b8b2ff47bac475069 Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Thu, 27 May 2021 20:23:19 +0300 Subject: [PATCH 1/4] CustomSongs: Restore custom song list after reload Uses the File System Access API supported in some browsers to keep the custom song list between sessions, restoring it back even when the page was closed. --- public/src/js/abstractfile.js | 32 +++++++ public/src/js/assets.js | 3 +- public/src/js/customsongs.js | 157 ++++++++++++++++++++++++---------- public/src/js/idb.js | 51 +++++++++++ public/src/js/loader.js | 1 + public/src/js/main.js | 1 + public/src/js/songselect.js | 14 +-- public/src/js/titlescreen.js | 35 +++++--- 8 files changed, 230 insertions(+), 64 deletions(-) create mode 100644 public/src/js/idb.js diff --git a/public/src/js/abstractfile.js b/public/src/js/abstractfile.js index 93d176a..44b4bbb 100644 --- a/public/src/js/abstractfile.js +++ b/public/src/js/abstractfile.js @@ -4,6 +4,21 @@ function readFile(file, arrayBuffer, encoding){ reader[arrayBuffer ? "readAsArrayBuffer" : "readAsText"](file, encoding) return promise } +function filePermission(file){ + return file.queryPermission().then(response => { + if(response === "granted"){ + return file + }else{ + return file.requestPermission().then(response => { + if(response === "granted"){ + return file + }else{ + return Promise.reject(file) + } + }) + } + }) +} class RemoteFile{ constructor(url){ this.url = url @@ -54,6 +69,23 @@ class LocalFile{ return Promise.resolve(this.file) } } +class FilesystemFile{ + constructor(file, path){ + this.file = file + this.path = path + this.url = this.path + this.name = file.name + } + arrayBuffer(){ + return this.blob().then(blob => blob.arrayBuffer()) + } + read(encoding){ + return this.blob().then(blob => readFile(blob, false, encoding)) + } + blob(){ + return filePermission(this.file).then(file => file.getFile()) + } +} class GdriveFile{ constructor(fileObj){ this.path = fileObj.path diff --git a/public/src/js/assets.js b/public/src/js/assets.js index c8b23cb..f449487 100644 --- a/public/src/js/assets.js +++ b/public/src/js/assets.js @@ -35,7 +35,8 @@ var assets = { "account.js", "lyrics.js", "customsongs.js", - "abstractfile.js" + "abstractfile.js", + "idb.js" ], "css": [ "main.css", diff --git a/public/src/js/customsongs.js b/public/src/js/customsongs.js index 6edc60c..ab98800 100644 --- a/public/src/js/customsongs.js +++ b/public/src/js/customsongs.js @@ -1,12 +1,23 @@ class CustomSongs{ - constructor(touchEnabled){ + constructor(touchEnabled, noPage){ + this.loaderDiv = document.createElement("div") + this.loaderDiv.innerHTML = assets.pages["loadsong"] + var loadingText = this.loaderDiv.querySelector("#loading-text") + this.setAltText(loadingText, strings.loading) + + this.locked = false + this.mode = "main" + + if(noPage){ + this.noPage = true + return + } + this.touchEnabled = touchEnabled loader.changePage("customsongs", true) if(touchEnabled){ this.getElement("view-outer").classList.add("touch-enabled") } - this.locked = false - this.mode = "main" var tutorialTitle = this.getElement("view-title") this.setAltText(tutorialTitle, strings.customSongs.title) @@ -19,7 +30,7 @@ class CustomSongs{ this.items = [] this.linkLocalFolder = document.getElementById("link-localfolder") - this.hasLocal = "webkitdirectory" in HTMLInputElement.prototype && !(/Android|iPhone|iPad/.test(navigator.userAgent)) + this.hasLocal = (typeof showDirectoryPicker === "function" || "webkitdirectory" in HTMLInputElement.prototype) && !(/Android|iPhone|iPad/.test(navigator.userAgent)) this.selected = -1 if(this.hasLocal){ @@ -68,12 +79,7 @@ class CustomSongs{ this.selected = this.items.length - 1 } - this.loaderDiv = document.createElement("div") - this.loaderDiv.innerHTML = assets.pages["loadsong"] - var loadingText = this.loaderDiv.querySelector("#loading-text") - this.setAltText(loadingText, strings.loading) - - if(DataTransferItem.prototype.webkitGetAsEntry){ + if(DataTransferItem.prototype.getAsFileSystemHandle || DataTransferItem.prototype.webkitGetAsEntry){ this.dropzone = document.getElementById("dropzone") var dropContent = this.dropzone.getElementsByClassName("view-content")[0] dropContent.innerText = strings.customSongs.dropzone @@ -142,7 +148,19 @@ class CustomSongs{ return } this.changeSelected(this.linkLocalFolder) - this.browse.click() + if(typeof showDirectoryPicker === "function"){ + return showDirectoryPicker().then(file => { + this.walkFilesystem(file).then(files => this.importLocal(files)).then(e => { + db.setItem("customFolder", file) + }).catch(e => { + if(e !== "cancel"){ + return Promise.reject(e) + } + }) + }, () => {}) + }else{ + this.browse.click() + } } browseChange(event){ var files = [] @@ -151,6 +169,24 @@ class CustomSongs{ } this.importLocal(files) } + walkFilesystem(dir, path=dir.name + "/", output=[]){ + return filePermission(dir).then(dir => { + var values = dir.values() + var walkValues = () => values.next().then(generator => { + if(generator.done){ + return output + } + var file = generator.value + if(file.kind === "directory"){ + return this.walkFilesystem(file, path + file.name + "/", output).then(() => walkValues()) + }else{ + output.push(new FilesystemFile(file, path + file.name)) + return walkValues() + } + }) + return walkValues() + }, () => Promise.resolve()) + } filesDropped(event){ event.preventDefault() this.dropzone.classList.remove("dragover") @@ -158,46 +194,69 @@ class CustomSongs{ if(this.locked){ return } - var files = [] - var walk = (entry, path="") => { - return new Promise(resolve => { - if(entry.isFile){ - entry.file(file => { - files.push(new LocalFile(file, path + file.name)) - return resolve() - }, resolve) - }else if(entry.isDirectory){ - var dirReader = entry.createReader() - dirReader.readEntries(entries => { - var dirPromises = [] - for(var i = 0; i < entries.length; i++){ - dirPromises.push(walk(entries[i], path + entry.name + "/")) - } - return Promise.all(dirPromises).then(resolve) - }, resolve) - }else{ - return resolve() - } - }) - } + var allFiles = [] var dropPromises = [] - for(var i = 0; i < event.dataTransfer.items.length; i++){ - var entry = event.dataTransfer.items[i].webkitGetAsEntry() - if(entry){ - dropPromises.push(walk(entry)) + var dropLength = event.dataTransfer.items.length + for(var i = 0; i < dropLength; i++){ + var item = event.dataTransfer.items[i] + let promise + if(item.getAsFileSystemHandle){ + promise = item.getAsFileSystemHandle().then(file => { + if(file.kind === "directory"){ + return this.walkFilesystem(file).then(files => { + if(files.length && dropLength === 1){ + db.setItem("customFolder", file) + } + return files + }) + }else{ + return [new FilesystemFile(file, file.name)] + } + }) + }else{ + var entry = item.webkitGetAsEntry() + if(entry){ + promise = this.walkEntry(entry) + } + } + if(promise){ + dropPromises.push(promise.then(files => { + allFiles = allFiles.concat(files) + })) } } - Promise.all(dropPromises).then(() => this.importLocal(files)) + Promise.all(dropPromises).then(() => this.importLocal(allFiles)) + } + walkEntry(entry, path="", output=[]){ + return new Promise(resolve => { + if(entry.isFile){ + entry.file(file => { + output.push(new LocalFile(file, path + file.name)) + return resolve() + }, resolve) + }else if(entry.isDirectory){ + var dirReader = entry.createReader() + dirReader.readEntries(entries => { + var dirPromises = [] + for(var i = 0; i < entries.length; i++){ + dirPromises.push(this.walkEntry(entries[i], path + entry.name + "/", output)) + } + return Promise.all(dirPromises).then(resolve) + }, resolve) + }else{ + return resolve() + } + }).then(() => output) } importLocal(files){ if(!files.length){ - return + return Promise.resolve("cancel") } this.locked = true this.loading(true) var importSongs = new ImportSongs() - importSongs.load(files).then(this.songsLoaded.bind(this), e => { + return importSongs.load(files).then(this.songsLoaded.bind(this), e => { this.browse.parentNode.reset() this.locked = false this.loading(false) @@ -315,7 +374,7 @@ class CustomSongs{ var length = songs.length assets.songs = songs assets.customSongs = true - assets.customSelected = 0 + assets.customSelected = this.noPage ? +localStorage.getItem("customSelected") : 0 } assets.sounds["se_don"].play() this.clean() @@ -393,15 +452,18 @@ class CustomSongs{ touched = this.touchEnabled } this.clean() - assets.sounds[confirm ? "se_don" : "se_cancel"].play() - setTimeout(() => { + if(!this.noPage){ + assets.sounds[confirm ? "se_don" : "se_cancel"].play() + } + return new Promise(resolve => setTimeout(() => { new SongSelect("customSongs", false, touched) - }, 500) + resolve() + }, 500)) } showError(text){ this.locked = false this.loading(false) - if(this.mode === "error"){ + if(this.noPage || this.mode === "error"){ return } this.mode = "error" @@ -418,6 +480,10 @@ class CustomSongs{ assets.sounds[confirm ? "se_don" : "se_cancel"].play() } clean(){ + delete this.loaderDiv + if(this.noPage){ + return + } this.keyboard.clean() this.gamepad.clean() pageEvents.remove(this.browse, "change") @@ -443,7 +509,6 @@ class CustomSongs{ delete this.linkPrivacy delete this.endButton delete this.items - delete this.loaderDiv delete this.errorDiv delete this.errorContent delete this.errorEnd diff --git a/public/src/js/idb.js b/public/src/js/idb.js new file mode 100644 index 0000000..6ca2640 --- /dev/null +++ b/public/src/js/idb.js @@ -0,0 +1,51 @@ +class IDB{ + constructor(name, store){ + this.name = name + this.store = store + } + init(){ + if(this.db){ + return Promise.resolve(this.db) + } + var request = indexedDB.open(this.name) + request.onupgradeneeded = event => { + var db = event.target.result + db.createObjectStore(this.store) + } + return this.promise(request).then(result => { + this.db = result + return this.db + }, target => + console.warn("DB error", target) + ) + } + promise(request){ + return new Promise((resolve, reject) => { + return pageEvents.race(request, "success", "error").then(response => { + if(response.type === "success"){ + return resolve(event.target.result) + }else{ + return reject(event.target) + } + }) + }) + } + transaction(method, ...args){ + return this.init().then(db => + db.transaction(this.store, "readwrite").objectStore(this.store)[method](...args) + ).then(this.promise.bind(this)) + } + getItem(name){ + return this.transaction("get", name) + } + setItem(name, value){ + return this.transaction("put", value, name) + } + removeItem(name){ + return this.transaction("delete", name) + } + removeDB(){ + delete this.db + return indexedDB.deleteDatabase(this.name) + } +} diff --git a/public/src/js/loader.js b/public/src/js/loader.js index b077deb..9053d99 100644 --- a/public/src/js/loader.js +++ b/public/src/js/loader.js @@ -252,6 +252,7 @@ class Loader{ settings = new Settings() pageEvents.setKbd() scoreStorage = new ScoreStorage() + db = new IDB("taiko", "store") Promise.all(this.promises).then(() => { if(this.error){ diff --git a/public/src/js/main.js b/public/src/js/main.js index b314147..2077fcd 100644 --- a/public/src/js/main.js +++ b/public/src/js/main.js @@ -90,6 +90,7 @@ var settings var scoreStorage var account = {} var gpicker +var db pageEvents.add(root, ["touchstart", "touchmove", "touchend"], event => { if(event.cancelable && cancelTouch && event.target.tagName !== "SELECT"){ diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index f775e07..6478ef3 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -210,7 +210,7 @@ class SongSelect{ if(!assets.customSongs && !fromTutorial && !("selectedSong" in localStorage) && !songId){ fromTutorial = touchEnabled ? "about" : "tutorial" } - if(p2.session){ + if(p2.session || assets.customSongs && "customSelected" in localStorage){ fromTutorial = false } @@ -231,7 +231,7 @@ class SongSelect{ if(songIdIndex !== -1){ this.selectedSong = songIdIndex }else if(assets.customSongs){ - this.selectedSong = assets.customSelected + this.selectedSong = Math.min(Math.max(0, assets.customSelected), this.songs.length - 1) }else if((!p2.session || fadeIn) && "selectedSong" in localStorage){ this.selectedSong = Math.min(Math.max(0, localStorage["selectedSong"] |0), this.songs.length - 1) } @@ -508,7 +508,7 @@ class SongSelect{ moveTo = "account" }else if(p2.session && 438 < mouse.x && mouse.x < 834 && mouse.y > 603){ moveTo = "session" - }else if(!p2.session && mouse.x > 641 && mouse.y > 603 && p2.socket.readyState === 1 && !assets.customSongs){ + }else if(!p2.session && mouse.x > 641 && mouse.y > 603 && p2.socket && p2.socket.readyState === 1 && !assets.customSongs){ moveTo = "session" }else{ var moveTo = this.songSelMouse(mouse.x, mouse.y) @@ -739,6 +739,7 @@ class SongSelect{ try{ if(assets.customSongs){ assets.customSelected = this.selectedSong + localStorage["customSelected"] = this.selectedSong }else{ localStorage["selectedSong"] = this.selectedSong } @@ -832,7 +833,7 @@ class SongSelect{ this.state.moveHover = null }else{ localStorage["selectedSong"] = this.selectedSong - + this.playSound("se_don") this.clean() setTimeout(() => { @@ -850,6 +851,8 @@ class SongSelect{ setTimeout(() => { new SongSelect("customSongs", false, this.touchEnabled) }, 500) + localStorage.removeItem("customSelected") + db.removeItem("customFolder") pageEvents.send("import-songs-default") }else{ localStorage["selectedSong"] = this.selectedSong @@ -1174,6 +1177,7 @@ class SongSelect{ this.state.locked = 2 if(assets.customSongs){ assets.customSelected = this.selectedSong + localStorage["customSelected"] = this.selectedSong }else if(!p2.session){ try{ localStorage["selectedSong"] = this.selectedSong @@ -2097,7 +2101,7 @@ class SongSelect{ ctx.lineTo(x + 4, y + 4) ctx.lineTo(x + 4, y + h) ctx.fill() - if(screen !== "difficulty" && p2.socket.readyState === 1 && !assets.customSongs){ + if(screen !== "difficulty" && p2.socket && p2.socket.readyState === 1 && !assets.customSongs){ var elapsed = (ms - this.state.screenMS) % 3100 var fade = 1 if(!p2.session && screen === "song"){ diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index aa98e4d..d1d3b2a 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -1,6 +1,7 @@ class Titlescreen{ constructor(songId){ this.songId = songId + db.getItem("customFolder").then(folder => this.customFolder = folder) if(!songId){ loader.changePage("titlescreen", false) @@ -50,7 +51,7 @@ class Titlescreen{ onPressed(pressed, name){ if(pressed){ - if(name === "gamepadConfirm" && snd.buffer.context.state === "suspended"){ + if(name === "gamepadConfirm" && (snd.buffer.context.state === "suspended" || this.customFolder)){ return } this.titleScreen.style.cursor = "auto" @@ -62,18 +63,28 @@ class Titlescreen{ goNext(fromP2){ if(p2.session && !fromP2){ p2.send("songsel") - }else if(fromP2 || localStorage.getItem("tutorial") === "true"){ - if(this.touched){ - localStorage.setItem("tutorial", "true") - } - pageEvents.remove(p2, "message") - setTimeout(() => { - new SongSelect(false, false, this.touched, this.songId) - }, 500) }else{ - setTimeout(() => { - new SettingsView(this.touched, true, this.songId) - }, 500) + if(fromP2 || this.customFolder || localStorage.getItem("tutorial") === "true"){ + if(this.touched){ + localStorage.setItem("tutorial", "true") + } + pageEvents.remove(p2, "message") + if(this.customFolder && !fromP2 && !assets.customSongs){ + var customSongs = new CustomSongs(this.touched, true) + customSongs.walkFilesystem(this.customFolder).then(files => customSongs.importLocal(files)).catch(() => { + db.removeItem("customFolder") + new SongSelect(false, false, this.touched, this.songId) + }) + }else{ + setTimeout(() => { + new SongSelect(false, false, this.touched, this.songId) + }, 500) + } + }else{ + setTimeout(() => { + new SettingsView(this.touched, true, this.songId) + }, 500) + } } } setLang(lang, noEvent){ From 9c44d223c4f69e81e715f27c590f78603682d6e4 Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Fri, 28 May 2021 04:55:53 +0300 Subject: [PATCH 2/4] Play se_don on title screen more fittingly --- public/src/js/customsongs.js | 7 ++++++- public/src/js/songselect.js | 2 +- public/src/js/titlescreen.js | 19 ++++++++++++++++--- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/public/src/js/customsongs.js b/public/src/js/customsongs.js index ab98800..9291b5f 100644 --- a/public/src/js/customsongs.js +++ b/public/src/js/customsongs.js @@ -363,6 +363,9 @@ class CustomSongs{ open("privacy") } loading(show){ + if(this.noPage){ + return + } if(show){ loader.screen.appendChild(this.loaderDiv) }else if(this.loaderDiv.parentNode){ @@ -376,7 +379,9 @@ class CustomSongs{ assets.customSongs = true assets.customSelected = this.noPage ? +localStorage.getItem("customSelected") : 0 } - assets.sounds["se_don"].play() + if(!this.noPage){ + assets.sounds["se_don"].play() + } this.clean() setTimeout(() => { new SongSelect("customSongs", false, this.touchEnabled) diff --git a/public/src/js/songselect.js b/public/src/js/songselect.js index 6478ef3..03028bb 100644 --- a/public/src/js/songselect.js +++ b/public/src/js/songselect.js @@ -757,7 +757,7 @@ class SongSelect{ autoplay = true }else if(shift){ autoplay = shift - }else if(p2.socket.readyState === 1 && !assets.customSongs){ + }else if(p2.socket && p2.socket.readyState === 1 && !assets.customSongs){ multiplayer = ctrl } var diff = this.difficultyId[difficulty] diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index d1d3b2a..850f391 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -56,7 +56,9 @@ class Titlescreen{ } this.titleScreen.style.cursor = "auto" this.clean() - assets.sounds["se_don"].play() + if(!this.customFolder || assets.customSongs){ + assets.sounds["se_don"].play() + } this.goNext() } } @@ -71,9 +73,20 @@ class Titlescreen{ pageEvents.remove(p2, "message") if(this.customFolder && !fromP2 && !assets.customSongs){ var customSongs = new CustomSongs(this.touched, true) - customSongs.walkFilesystem(this.customFolder).then(files => customSongs.importLocal(files)).catch(() => { + var soundPlayed = false + customSongs.walkFilesystem(this.customFolder).then(files => { + assets.sounds["se_don"].play() + soundPlayed = true + return customSongs.importLocal(files) + }).catch(() => { + localStorage.removeItem("customSelected") db.removeItem("customFolder") - new SongSelect(false, false, this.touched, this.songId) + if(!soundPlayed){ + assets.sounds["se_don"].play() + } + setTimeout(() => { + new SongSelect(false, false, this.touched, this.songId) + }, 500) }) }else{ setTimeout(() => { From 657c6317698192497991fc63feb7fb958217bb60 Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Sun, 30 May 2021 07:13:36 +0300 Subject: [PATCH 3/4] Support restoring multiple folders imported by dragging --- public/src/js/customsongs.js | 57 ++++++++++++++++-------------------- public/src/js/titlescreen.js | 9 ++++-- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/public/src/js/customsongs.js b/public/src/js/customsongs.js index 9291b5f..2a7a5a6 100644 --- a/public/src/js/customsongs.js +++ b/public/src/js/customsongs.js @@ -151,7 +151,7 @@ class CustomSongs{ if(typeof showDirectoryPicker === "function"){ return showDirectoryPicker().then(file => { this.walkFilesystem(file).then(files => this.importLocal(files)).then(e => { - db.setItem("customFolder", file) + db.setItem("customFolder", [file]) }).catch(e => { if(e !== "cancel"){ return Promise.reject(e) @@ -169,23 +169,22 @@ class CustomSongs{ } this.importLocal(files) } - walkFilesystem(dir, path=dir.name + "/", output=[]){ - return filePermission(dir).then(dir => { - var values = dir.values() - var walkValues = () => values.next().then(generator => { - if(generator.done){ - return output - } - var file = generator.value - if(file.kind === "directory"){ - return this.walkFilesystem(file, path + file.name + "/", output).then(() => walkValues()) - }else{ - output.push(new FilesystemFile(file, path + file.name)) - return walkValues() - } - }) - return walkValues() - }, () => Promise.resolve()) + walkFilesystem(file, path="", output=[]){ + if(file.kind === "directory"){ + return filePermission(file).then(file => { + var values = file.values() + var walkValues = () => values.next().then(generator => { + if(generator.done){ + return output + } + return this.walkFilesystem(generator.value, path + file.name + "/", output).then(() => walkValues()) + }) + return walkValues() + }, () => Promise.resolve()) + }else{ + output.push(new FilesystemFile(file, path + file.name)) + return Promise.resolve(output) + } } filesDropped(event){ event.preventDefault() @@ -196,22 +195,14 @@ class CustomSongs{ } var allFiles = [] var dropPromises = [] - var dropLength = event.dataTransfer.items.length - for(var i = 0; i < dropLength; i++){ + var dbItems = [] + for(var i = 0; i < event.dataTransfer.items.length; i++){ var item = event.dataTransfer.items[i] let promise if(item.getAsFileSystemHandle){ promise = item.getAsFileSystemHandle().then(file => { - if(file.kind === "directory"){ - return this.walkFilesystem(file).then(files => { - if(files.length && dropLength === 1){ - db.setItem("customFolder", file) - } - return files - }) - }else{ - return [new FilesystemFile(file, file.name)] - } + dbItems.push(file) + return this.walkFilesystem(file) }) }else{ var entry = item.webkitGetAsEntry() @@ -225,7 +216,11 @@ class CustomSongs{ })) } } - Promise.all(dropPromises).then(() => this.importLocal(allFiles)) + Promise.all(dropPromises).then(() => this.importLocal(allFiles)).then(() => { + if(dbItems.length){ + db.setItem("customFolder", dbItems) + } + }) } walkEntry(entry, path="", output=[]){ return new Promise(resolve => { diff --git a/public/src/js/titlescreen.js b/public/src/js/titlescreen.js index 850f391..89de402 100644 --- a/public/src/js/titlescreen.js +++ b/public/src/js/titlescreen.js @@ -74,10 +74,15 @@ class Titlescreen{ if(this.customFolder && !fromP2 && !assets.customSongs){ var customSongs = new CustomSongs(this.touched, true) var soundPlayed = false - customSongs.walkFilesystem(this.customFolder).then(files => { + var promises = [] + var allFiles = [] + this.customFolder.forEach(file => { + promises.push(customSongs.walkFilesystem(file, undefined, allFiles)) + }) + Promise.all(promises).then(() => { assets.sounds["se_don"].play() soundPlayed = true - return customSongs.importLocal(files) + return customSongs.importLocal(allFiles) }).catch(() => { localStorage.removeItem("customSelected") db.removeItem("customFolder") From 3d09fea3a5644b9e033fa4ddacfaba891f3a7da5 Mon Sep 17 00:00:00 2001 From: LoveEevee Date: Tue, 1 Jun 2021 12:21:55 +0300 Subject: [PATCH 4/4] Workaround an http-only crash in Chrome, fix cancel on title screen --- public/src/js/customsongs.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/public/src/js/customsongs.js b/public/src/js/customsongs.js index 2a7a5a6..34ae66e 100644 --- a/public/src/js/customsongs.js +++ b/public/src/js/customsongs.js @@ -79,7 +79,8 @@ class CustomSongs{ this.selected = this.items.length - 1 } - if(DataTransferItem.prototype.getAsFileSystemHandle || DataTransferItem.prototype.webkitGetAsEntry){ + this.fileSystem = location.protocol === "https:" && DataTransferItem.prototype.getAsFileSystemHandle + if(this.fileSystem || DataTransferItem.prototype.webkitGetAsEntry){ this.dropzone = document.getElementById("dropzone") var dropContent = this.dropzone.getElementsByClassName("view-content")[0] dropContent.innerText = strings.customSongs.dropzone @@ -199,7 +200,7 @@ class CustomSongs{ for(var i = 0; i < event.dataTransfer.items.length; i++){ var item = event.dataTransfer.items[i] let promise - if(item.getAsFileSystemHandle){ + if(this.fileSystem){ promise = item.getAsFileSystemHandle().then(file => { dbItems.push(file) return this.walkFilesystem(file) @@ -245,7 +246,11 @@ class CustomSongs{ } importLocal(files){ if(!files.length){ - return Promise.resolve("cancel") + if(this.noPage){ + return Promise.reject("cancel") + }else{ + return Promise.resolve("cancel") + } } this.locked = true this.loading(true)