ImportSongs: Implement Google Drive beta testing
Instances that wish to enable Google Drive support should first enable it to only a small subset of users (100 maximum) to allow the OAuth screen to be verified by Google without hitting the user limit. Minimum level in the config can be set to enable beta testing of this feature and then disabled by setting it to None. - Add user level assignment screen to the administration panel - Add privacy policy and links to it in various places - Add switch accounts link near the Google Drive picker
This commit is contained in:
@@ -112,10 +112,15 @@ kbd{
|
||||
margin-right: 0.4em;
|
||||
}
|
||||
.center-buttons{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 1.5em 0;
|
||||
}
|
||||
.account-view .center-buttons{
|
||||
margin: 0.3em 0;
|
||||
}
|
||||
.center-buttons>div{
|
||||
text-align: center;
|
||||
margin: 0.2em 0;
|
||||
}
|
||||
.center-buttons .taibtn{
|
||||
margin: 0 0.2em;
|
||||
}
|
||||
|
||||
@@ -93,6 +93,11 @@ class Account{
|
||||
this.inputForms.push(this.accountDel.password)
|
||||
this.accountDelDiv = this.getElement("accountdel-div")
|
||||
|
||||
this.linkPrivacy = this.getElement("privacy-btn")
|
||||
this.setAltText(this.linkPrivacy, strings.account.privacy)
|
||||
pageEvents.add(this.linkPrivacy, ["mousedown", "touchstart"], this.openPrivacy.bind(this))
|
||||
this.items.push(this.linkPrivacy)
|
||||
|
||||
this.logoutButton = this.getElement("logout-btn")
|
||||
this.setAltText(this.logoutButton, strings.account.logout)
|
||||
pageEvents.add(this.logoutButton, ["mousedown", "touchstart"], this.onLogout.bind(this))
|
||||
@@ -245,6 +250,12 @@ class Account{
|
||||
|
||||
pageEvents.add(this.registerButton, ["mousedown", "touchstart"], this.onSwitchMode.bind(this))
|
||||
this.items.push(this.registerButton)
|
||||
|
||||
this.linkPrivacy = this.getElement("privacy-btn")
|
||||
this.setAltText(this.linkPrivacy, strings.account.privacy)
|
||||
pageEvents.add(this.linkPrivacy, ["mousedown", "touchstart"], this.openPrivacy.bind(this))
|
||||
this.items.push(this.linkPrivacy)
|
||||
|
||||
if(!register){
|
||||
this.items.push(this.loginButton)
|
||||
}
|
||||
@@ -282,11 +293,17 @@ class Account{
|
||||
this.onSwitchMode()
|
||||
}else if(selected === this.loginButton){
|
||||
this.onLogin()
|
||||
}else if(selected === this.linkPrivacy){
|
||||
assets.sounds["se_don"].play()
|
||||
this.openPrivacy()
|
||||
}
|
||||
}else if(name === "previous" || name === "next"){
|
||||
selected.classList.remove("selected")
|
||||
this.selected = this.mod(this.items.length, this.selected + (name === "next" ? 1 : -1))
|
||||
this.items[this.selected].classList.add("selected")
|
||||
if(this.items[this.selected] === this.linkPrivacy){
|
||||
this.items[this.selected].scrollIntoView()
|
||||
}
|
||||
assets.sounds["se_ka"].play()
|
||||
}else if(name === "back"){
|
||||
this.onEnd()
|
||||
@@ -380,6 +397,19 @@ class Account{
|
||||
}
|
||||
})
|
||||
}
|
||||
openPrivacy(event){
|
||||
if(event){
|
||||
if(event.type === "touchstart"){
|
||||
event.preventDefault()
|
||||
}else if(event.which !== 1){
|
||||
return
|
||||
}
|
||||
}
|
||||
if(this.locked){
|
||||
return
|
||||
}
|
||||
open("privacy")
|
||||
}
|
||||
onLogout(){
|
||||
if(event){
|
||||
if(event.type === "touchstart"){
|
||||
@@ -583,6 +613,7 @@ class Account{
|
||||
pageEvents.remove(this.customdonResetBtn, ["click", "touchstart"])
|
||||
pageEvents.remove(this.accounPassButton, ["click", "touchstart"])
|
||||
pageEvents.remove(this.accountDelButton, ["click", "touchstart"])
|
||||
pageEvents.remove(this.linkPrivacy, ["mousedown", "touchstart"])
|
||||
pageEvents.remove(this.logoutButton, ["mousedown", "touchstart"])
|
||||
pageEvents.remove(this.saveButton, ["mousedown", "touchstart"])
|
||||
for(var i = 0; i < this.inputForms.length; i++){
|
||||
@@ -602,6 +633,7 @@ class Account{
|
||||
delete this.accountDelButton
|
||||
delete this.accountDel
|
||||
delete this.accountDelDiv
|
||||
delete this.linkPrivacy
|
||||
delete this.logoutButton
|
||||
delete this.saveButton
|
||||
delete this.inputForms
|
||||
@@ -615,12 +647,14 @@ class Account{
|
||||
for(var i = 0; i < this.form.length; i++){
|
||||
pageEvents.remove(this.registerButton, ["keydown", "keyup", "keypress"])
|
||||
}
|
||||
pageEvents.remove(this.linkPrivacy, ["mousedown", "touchstart"])
|
||||
delete this.errorDiv
|
||||
delete this.form
|
||||
delete this.password2
|
||||
delete this.remember
|
||||
delete this.loginButton
|
||||
delete this.registerButton
|
||||
delete this.linkPrivacy
|
||||
}
|
||||
pageEvents.remove(this.endButton, ["mousedown", "touchstart"])
|
||||
delete this.endButton
|
||||
|
||||
@@ -36,7 +36,10 @@ class CustomSongs{
|
||||
this.linkLocalFolder.parentNode.removeChild(this.linkLocalFolder)
|
||||
}
|
||||
|
||||
var groupGdrive = document.getElementById("group-gdrive")
|
||||
this.linkGdriveFolder = document.getElementById("link-gdrivefolder")
|
||||
this.linkGdriveAccount = document.getElementById("link-gdriveaccount")
|
||||
this.linkPrivacy = document.getElementById("link-privacy")
|
||||
if(gameConfig.google_credentials.gdrive_enabled){
|
||||
this.setAltText(this.linkGdriveFolder, strings.customSongs.gdriveFolder)
|
||||
pageEvents.add(this.linkGdriveFolder, ["mousedown", "touchstart"], this.gdriveFolder.bind(this))
|
||||
@@ -45,8 +48,14 @@ class CustomSongs{
|
||||
this.linkGdriveFolder.classList.add("selected")
|
||||
this.selected = this.items.length - 1
|
||||
}
|
||||
this.setAltText(this.linkGdriveAccount, strings.customSongs.gdriveAccount)
|
||||
pageEvents.add(this.linkGdriveAccount, ["mousedown", "touchstart"], this.gdriveAccount.bind(this))
|
||||
this.items.push(this.linkGdriveAccount)
|
||||
this.setAltText(this.linkPrivacy, strings.account.privacy)
|
||||
pageEvents.add(this.linkPrivacy, ["mousedown", "touchstart"], this.openPrivacy.bind(this))
|
||||
this.items.push(this.linkPrivacy)
|
||||
}else{
|
||||
this.linkGdriveFolder.parentNode.removeChild(this.linkGdriveFolder)
|
||||
groupGdrive.style.display = "none"
|
||||
}
|
||||
|
||||
this.endButton = this.getElement("view-end-button")
|
||||
@@ -237,13 +246,67 @@ class CustomSongs{
|
||||
}else if(e !== "cancel"){
|
||||
return Promise.reject(e)
|
||||
}
|
||||
}).finally(() => {
|
||||
var addRemove = !gpicker || !gpicker.oauthToken ? "add" : "remove"
|
||||
this.linkGdriveAccount.classList[addRemove]("hiddenbtn")
|
||||
})
|
||||
}
|
||||
gdriveAccount(event){
|
||||
if(event){
|
||||
if(event.type === "touchstart"){
|
||||
event.preventDefault()
|
||||
}else if(event.which !== 1){
|
||||
return
|
||||
}
|
||||
}
|
||||
if(this.locked || this.mode !== "main"){
|
||||
return
|
||||
}
|
||||
this.changeSelected(this.linkGdriveAccount)
|
||||
this.locked = true
|
||||
this.loading(true)
|
||||
if(!gpicker){
|
||||
var gpickerPromise = loader.loadScript("/src/js/gpicker.js").then(() => {
|
||||
gpicker = new Gpicker()
|
||||
})
|
||||
}else{
|
||||
var gpickerPromise = Promise.resolve()
|
||||
}
|
||||
gpickerPromise.then(() => {
|
||||
return gpicker.switchAccounts(locked => {
|
||||
this.locked = locked
|
||||
this.loading(locked)
|
||||
}, error => {
|
||||
this.showError(error)
|
||||
})
|
||||
}).then(() => {
|
||||
this.locked = false
|
||||
this.loading(false)
|
||||
}).catch(error => {
|
||||
if(error !== "cancel"){
|
||||
this.showError(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
openPrivacy(event){
|
||||
if(event){
|
||||
if(event.type === "touchstart"){
|
||||
event.preventDefault()
|
||||
}else if(event.which !== 1){
|
||||
return
|
||||
}
|
||||
}
|
||||
if(this.locked || this.mode !== "main"){
|
||||
return
|
||||
}
|
||||
this.changeSelected(this.linkPrivacy)
|
||||
open("privacy")
|
||||
}
|
||||
loading(show){
|
||||
if(show){
|
||||
loader.screen.appendChild(this.loaderDiv)
|
||||
}else{
|
||||
loader.screen.removeChild(this.loaderDiv)
|
||||
}else if(this.loaderDiv.parentNode){
|
||||
this.loaderDiv.parentNode.removeChild(this.loaderDiv)
|
||||
}
|
||||
}
|
||||
songsLoaded(songs){
|
||||
@@ -276,6 +339,12 @@ class CustomSongs{
|
||||
}else if(selected === this.linkGdriveFolder){
|
||||
assets.sounds["se_don"].play()
|
||||
this.gdriveFolder()
|
||||
}else if(selected === this.linkGdriveAccount){
|
||||
assets.sounds["se_don"].play()
|
||||
this.gdriveAccount()
|
||||
}else if(selected === this.linkPrivacy){
|
||||
assets.sounds["se_don"].play()
|
||||
this.openPrivacy()
|
||||
}
|
||||
}
|
||||
}else if(name === "previous" || name === "next"){
|
||||
@@ -327,6 +396,8 @@ class CustomSongs{
|
||||
}, 500)
|
||||
}
|
||||
showError(text){
|
||||
this.locked = false
|
||||
this.loading(false)
|
||||
if(this.mode === "error"){
|
||||
return
|
||||
}
|
||||
@@ -352,6 +423,8 @@ class CustomSongs{
|
||||
}
|
||||
if(gameConfig.google_credentials.gdrive_enabled){
|
||||
pageEvents.remove(this.linkGdriveFolder, ["mousedown", "touchstart"])
|
||||
pageEvents.remove(this.linkGdriveAccount, ["mousedown", "touchstart"])
|
||||
pageEvents.remove(this.linkPrivacy, ["mousedown", "touchstart"])
|
||||
}
|
||||
pageEvents.remove(this.endButton, ["mousedown", "touchstart"])
|
||||
pageEvents.remove(this.errorDiv, ["mousedown", "touchstart"])
|
||||
@@ -363,6 +436,8 @@ class CustomSongs{
|
||||
delete this.browse
|
||||
delete this.linkLocalFolder
|
||||
delete this.linkGdriveFolder
|
||||
delete this.linkGdriveAccount
|
||||
delete this.linkPrivacy
|
||||
delete this.endButton
|
||||
delete this.items
|
||||
delete this.loaderDiv
|
||||
|
||||
@@ -131,37 +131,48 @@ class Gpicker{
|
||||
gapi.client.load("drive", "v3").then(resolve, reject)
|
||||
))
|
||||
}
|
||||
getToken(lockedCallback=()=>{}, errorCallback=()=>{}){
|
||||
if(this.oauthToken){
|
||||
return Promise.resolve()
|
||||
}
|
||||
getAuth(errorCallback=()=>{}){
|
||||
if(!this.auth){
|
||||
var authPromise = gapi.auth2.init({
|
||||
clientId: this.oauthClientId,
|
||||
fetch_basic_profile: false,
|
||||
scope: this.scope
|
||||
}).then(() => {
|
||||
this.auth = gapi.auth2.getAuthInstance()
|
||||
}, e => {
|
||||
if(e.details){
|
||||
errorCallback(strings.gpicker.authError.replace("%s", e.details))
|
||||
}
|
||||
return Promise.reject(e)
|
||||
return new Promise((resolve, reject) => {
|
||||
gapi.auth2.init({
|
||||
clientId: this.oauthClientId,
|
||||
fetch_basic_profile: false,
|
||||
scope: this.scope
|
||||
}).then(() => {
|
||||
this.auth = gapi.auth2.getAuthInstance()
|
||||
resolve(this.auth)
|
||||
}, e => {
|
||||
if(e.details){
|
||||
var errorStr = strings.gpicker.authError.replace("%s", e.details)
|
||||
if(/cookie/i.test(e.details)){
|
||||
errorStr += "\n\n" + strings.gpicker.cookieError
|
||||
}
|
||||
errorCallback(errorStr)
|
||||
}
|
||||
reject(e)
|
||||
})
|
||||
})
|
||||
}else{
|
||||
var authPromise = Promise.resolve()
|
||||
return Promise.resolve(this.auth)
|
||||
}
|
||||
return authPromise.then(() => {
|
||||
var user = this.auth.currentUser.get()
|
||||
if(!this.checkScope(user)){
|
||||
}
|
||||
getToken(lockedCallback=()=>{}, errorCallback=()=>{}, force){
|
||||
if(this.oauthToken && !force){
|
||||
return Promise.resolve()
|
||||
}
|
||||
return this.getAuth(errorCallback).then(auth => {
|
||||
var user = force || auth.currentUser.get()
|
||||
if(force || !this.checkScope(user)){
|
||||
lockedCallback(false)
|
||||
this.auth.signIn().then(user => {
|
||||
return auth.signIn(force ? {
|
||||
prompt: "select_account"
|
||||
} : undefined).then(user => {
|
||||
if(this.checkScope(user)){
|
||||
lockedCallback(true)
|
||||
}else{
|
||||
return Promise.reject("cancel")
|
||||
}
|
||||
})
|
||||
}, () => Promise.reject("cancel"))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -173,6 +184,9 @@ class Gpicker{
|
||||
return false
|
||||
}
|
||||
}
|
||||
switchAccounts(lockedCallback, errorCallback){
|
||||
return this.loadApi().then(() => this.getToken(lockedCallback, errorCallback, true))
|
||||
}
|
||||
displayPicker(callback){
|
||||
var picker = gapi.picker.api
|
||||
new picker.PickerBuilder()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
addEventListener("error", function(err){
|
||||
var stack
|
||||
if("error" in err){
|
||||
if("error" in err && err.error){
|
||||
stack = err.error.stack
|
||||
}else{
|
||||
stack = err.message + "\n at " + err.filename + ":" + err.lineno + ":" + err.colno
|
||||
|
||||
@@ -918,6 +918,13 @@ var translations = {
|
||||
tw: "註冊",
|
||||
ko: "가입하기"
|
||||
},
|
||||
privacy: {
|
||||
ja: "プライバシー",
|
||||
en: "Privacy",
|
||||
cn: "隐私权",
|
||||
tw: "隱私權",
|
||||
ko: "개인정보처리방침"
|
||||
},
|
||||
registerAccount: {
|
||||
ja: "アカウントを登録",
|
||||
en: "Register account",
|
||||
@@ -1135,6 +1142,13 @@ var translations = {
|
||||
tw: "Google雲端硬碟...",
|
||||
ko: "구글 드라이브..."
|
||||
},
|
||||
gdriveAccount: {
|
||||
ja: "アカウントの切り替え",
|
||||
en: "Switch Accounts",
|
||||
cn: "切换帐户",
|
||||
tw: "切換帳戶",
|
||||
ko: "계정 전환"
|
||||
},
|
||||
dropzone: {
|
||||
ja: "ここにファイルをドロップ",
|
||||
en: "Drop files here",
|
||||
@@ -1180,6 +1194,9 @@ var translations = {
|
||||
},
|
||||
authError: {
|
||||
en: "Auth error: %s"
|
||||
},
|
||||
cookieError: {
|
||||
en: "This function requires third party cookies."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
<input type="password" name="password">
|
||||
</div>
|
||||
</form>
|
||||
<div class="center-buttons">
|
||||
<div>
|
||||
<div class="privacy-btn taibtn stroke-sub link-btn"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="diag-txt"></div>
|
||||
<div class="left-buttons">
|
||||
|
||||
@@ -3,8 +3,14 @@
|
||||
<div class="view-title stroke-sub"></div>
|
||||
<div class="view-content"></div>
|
||||
<div class="center-buttons">
|
||||
<div id="link-localfolder" class="taibtn stroke-sub link-btn"></div>
|
||||
<div id="link-gdrivefolder" class="taibtn stroke-sub link-btn"></div>
|
||||
<div>
|
||||
<div id="link-localfolder" class="taibtn stroke-sub link-btn"></div>
|
||||
</div>
|
||||
<div id="group-gdrive">
|
||||
<div id="link-gdrivefolder" class="taibtn stroke-sub link-btn"></div>
|
||||
<div id="link-gdriveaccount" class="taibtn stroke-sub link-btn"></div>
|
||||
<div id="link-privacy" class="taibtn stroke-sub link-btn"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="view-end-button taibtn stroke-sub"></div>
|
||||
<div class="view-outer shadow-outer" id="dropzone">
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
</div>
|
||||
<div class="left-buttons">
|
||||
<div class="register-btn taibtn stroke-sub link-btn"></div>
|
||||
<div class="privacy-btn taibtn stroke-sub link-btn"></div>
|
||||
</div>
|
||||
<div class="view-end-button taibtn stroke-sub selected"></div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user