2018-04-26 00:11:10 +00:00
|
|
|
/**
|
|
|
|
* Script for login.ejs
|
|
|
|
*/
|
2018-04-25 21:06:10 +00:00
|
|
|
// Validation Regexes.
|
2018-04-25 21:40:46 +00:00
|
|
|
const validUsername = /^[a-zA-Z0-9_]{1,16}$/
|
|
|
|
const basicEmail = /^\S+@\S+\.\S+$/
|
2018-04-26 00:11:10 +00:00
|
|
|
//const validEmail = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i
|
2018-04-25 21:40:46 +00:00
|
|
|
|
|
|
|
// Login Elements
|
2018-05-31 02:22:17 +00:00
|
|
|
const loginCancelContainer = document.getElementById('loginCancelContainer')
|
|
|
|
const loginCancelButton = document.getElementById('loginCancelButton')
|
2018-04-25 21:40:46 +00:00
|
|
|
const loginEmailError = document.getElementById('loginEmailError')
|
|
|
|
const loginUsername = document.getElementById('loginUsername')
|
|
|
|
const loginPasswordError = document.getElementById('loginPasswordError')
|
|
|
|
const loginPassword = document.getElementById('loginPassword')
|
|
|
|
const checkmarkContainer = document.getElementById('checkmarkContainer')
|
|
|
|
const loginRememberOption = document.getElementById('loginRememberOption')
|
|
|
|
const loginButton = document.getElementById('loginButton')
|
2018-04-26 22:41:26 +00:00
|
|
|
const loginForm = document.getElementById('loginForm')
|
2018-04-25 21:06:10 +00:00
|
|
|
|
|
|
|
// Control variables.
|
|
|
|
let lu = false, lp = false
|
|
|
|
|
2018-04-25 21:40:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Show a login error.
|
|
|
|
*
|
|
|
|
* @param {HTMLElement} element The element on which to display the error.
|
|
|
|
* @param {string} value The error text.
|
|
|
|
*/
|
2018-04-25 21:06:10 +00:00
|
|
|
function showError(element, value){
|
|
|
|
element.innerHTML = value
|
|
|
|
element.style.opacity = 1
|
|
|
|
}
|
|
|
|
|
2018-04-25 21:40:46 +00:00
|
|
|
/**
|
|
|
|
* Shake a login error to add emphasis.
|
|
|
|
*
|
|
|
|
* @param {HTMLElement} element The element to shake.
|
|
|
|
*/
|
2018-04-25 21:06:10 +00:00
|
|
|
function shakeError(element){
|
|
|
|
if(element.style.opacity == 1){
|
|
|
|
element.classList.remove('shake')
|
|
|
|
void element.offsetWidth
|
|
|
|
element.classList.add('shake')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-25 21:40:46 +00:00
|
|
|
/**
|
|
|
|
* Validate that an email field is neither empty nor invalid.
|
|
|
|
*
|
|
|
|
* @param {string} value The email value.
|
|
|
|
*/
|
2018-04-25 21:06:10 +00:00
|
|
|
function validateEmail(value){
|
|
|
|
if(value){
|
|
|
|
if(!basicEmail.test(value) && !validUsername.test(value)){
|
2019-04-08 03:33:40 +00:00
|
|
|
showError(loginEmailError, Lang.queryJS('login.error.invalidValue'))
|
2018-04-25 21:06:10 +00:00
|
|
|
loginDisabled(true)
|
|
|
|
lu = false
|
|
|
|
} else {
|
|
|
|
loginEmailError.style.opacity = 0
|
|
|
|
lu = true
|
|
|
|
if(lp){
|
|
|
|
loginDisabled(false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lu = false
|
2019-04-08 03:33:40 +00:00
|
|
|
showError(loginEmailError, Lang.queryJS('login.error.requiredValue'))
|
2018-04-25 21:06:10 +00:00
|
|
|
loginDisabled(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-25 21:40:46 +00:00
|
|
|
/**
|
|
|
|
* Validate that the password field is not empty.
|
|
|
|
*
|
|
|
|
* @param {string} value The password value.
|
|
|
|
*/
|
2018-04-25 21:06:10 +00:00
|
|
|
function validatePassword(value){
|
|
|
|
if(value){
|
|
|
|
loginPasswordError.style.opacity = 0
|
|
|
|
lp = true
|
|
|
|
if(lu){
|
|
|
|
loginDisabled(false)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
lp = false
|
2019-04-08 03:33:40 +00:00
|
|
|
showError(loginPasswordError, Lang.queryJS('login.error.invalidValue'))
|
2018-04-25 21:06:10 +00:00
|
|
|
loginDisabled(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Emphasize errors with shake when focus is lost.
|
|
|
|
loginUsername.addEventListener('focusout', (e) => {
|
|
|
|
validateEmail(e.target.value)
|
|
|
|
shakeError(loginEmailError)
|
|
|
|
})
|
|
|
|
loginPassword.addEventListener('focusout', (e) => {
|
|
|
|
validatePassword(e.target.value)
|
|
|
|
shakeError(loginPasswordError)
|
|
|
|
})
|
|
|
|
|
|
|
|
// Validate input for each field.
|
|
|
|
loginUsername.addEventListener('input', (e) => {
|
|
|
|
validateEmail(e.target.value)
|
|
|
|
})
|
|
|
|
loginPassword.addEventListener('input', (e) => {
|
|
|
|
validatePassword(e.target.value)
|
|
|
|
})
|
|
|
|
|
2018-04-25 21:40:46 +00:00
|
|
|
/**
|
|
|
|
* Enable or disable the login button.
|
|
|
|
*
|
|
|
|
* @param {boolean} v True to enable, false to disable.
|
|
|
|
*/
|
2018-04-25 21:06:10 +00:00
|
|
|
function loginDisabled(v){
|
|
|
|
if(loginButton.disabled !== v){
|
|
|
|
loginButton.disabled = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-25 21:40:46 +00:00
|
|
|
/**
|
|
|
|
* Enable or disable loading elements.
|
|
|
|
*
|
|
|
|
* @param {boolean} v True to enable, false to disable.
|
|
|
|
*/
|
2018-04-25 21:06:10 +00:00
|
|
|
function loginLoading(v){
|
|
|
|
if(v){
|
|
|
|
loginButton.setAttribute('loading', v)
|
2019-04-08 03:33:40 +00:00
|
|
|
loginButton.innerHTML = loginButton.innerHTML.replace(Lang.queryJS('login.login'), Lang.queryJS('login.loggingIn'))
|
2018-04-25 21:06:10 +00:00
|
|
|
} else {
|
|
|
|
loginButton.removeAttribute('loading')
|
2019-04-08 03:33:40 +00:00
|
|
|
loginButton.innerHTML = loginButton.innerHTML.replace(Lang.queryJS('login.loggingIn'), Lang.queryJS('login.login'))
|
2018-04-25 21:06:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-25 21:40:46 +00:00
|
|
|
/**
|
|
|
|
* Enable or disable login form.
|
|
|
|
*
|
|
|
|
* @param {boolean} v True to enable, false to disable.
|
|
|
|
*/
|
2018-04-25 21:06:10 +00:00
|
|
|
function formDisabled(v){
|
|
|
|
loginDisabled(v)
|
2018-05-31 02:22:17 +00:00
|
|
|
loginCancelButton.disabled = v
|
2018-04-25 21:06:10 +00:00
|
|
|
loginUsername.disabled = v
|
|
|
|
loginPassword.disabled = v
|
|
|
|
if(v){
|
|
|
|
checkmarkContainer.setAttribute('disabled', v)
|
|
|
|
} else {
|
|
|
|
checkmarkContainer.removeAttribute('disabled')
|
|
|
|
}
|
|
|
|
loginRememberOption.disabled = v
|
|
|
|
}
|
|
|
|
|
2018-05-31 02:22:17 +00:00
|
|
|
let loginViewOnSuccess = VIEWS.landing
|
|
|
|
let loginViewOnCancel = VIEWS.settings
|
2018-08-22 14:54:09 +00:00
|
|
|
let loginViewCancelHandler
|
2018-05-31 02:22:17 +00:00
|
|
|
|
|
|
|
function loginCancelEnabled(val){
|
|
|
|
if(val){
|
|
|
|
$(loginCancelContainer).show()
|
|
|
|
} else {
|
|
|
|
$(loginCancelContainer).hide()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
loginCancelButton.onclick = (e) => {
|
|
|
|
switchView(getCurrentView(), loginViewOnCancel, 500, 500, () => {
|
2019-02-05 22:26:00 +00:00
|
|
|
loginUsername.value = ''
|
|
|
|
loginPassword.value = ''
|
2018-05-31 02:22:17 +00:00
|
|
|
loginCancelEnabled(false)
|
2018-08-22 14:54:09 +00:00
|
|
|
if(loginViewCancelHandler != null){
|
|
|
|
loginViewCancelHandler()
|
|
|
|
loginViewCancelHandler = null
|
|
|
|
}
|
2018-05-31 02:22:17 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-04-26 22:41:26 +00:00
|
|
|
// Disable default form behavior.
|
|
|
|
loginForm.onsubmit = () => { return false }
|
|
|
|
|
2018-04-25 21:40:46 +00:00
|
|
|
// Bind login button behavior.
|
2018-04-25 21:06:10 +00:00
|
|
|
loginButton.addEventListener('click', () => {
|
|
|
|
// Disable form.
|
|
|
|
formDisabled(true)
|
|
|
|
|
|
|
|
// Show loading stuff.
|
|
|
|
loginLoading(true)
|
|
|
|
|
2022-02-12 00:51:28 +00:00
|
|
|
AuthManager.addMojangAccount(loginUsername.value, loginPassword.value).then((value) => {
|
2018-04-29 22:05:59 +00:00
|
|
|
updateSelectedAccount(value)
|
2019-04-08 03:33:40 +00:00
|
|
|
loginButton.innerHTML = loginButton.innerHTML.replace(Lang.queryJS('login.loggingIn'), Lang.queryJS('login.success'))
|
2018-04-25 21:06:10 +00:00
|
|
|
$('.circle-loader').toggleClass('load-complete')
|
|
|
|
$('.checkmark').toggle()
|
|
|
|
setTimeout(() => {
|
2023-02-25 02:02:18 +00:00
|
|
|
switchView(VIEWS.login, loginViewOnSuccess, 500, 500, async () => {
|
2018-05-31 02:22:17 +00:00
|
|
|
// Temporary workaround
|
|
|
|
if(loginViewOnSuccess === VIEWS.settings){
|
2023-02-25 02:02:18 +00:00
|
|
|
await prepareSettings()
|
2018-05-31 02:22:17 +00:00
|
|
|
}
|
|
|
|
loginViewOnSuccess = VIEWS.landing // Reset this for good measure.
|
|
|
|
loginCancelEnabled(false) // Reset this for good measure.
|
2018-08-22 14:54:09 +00:00
|
|
|
loginViewCancelHandler = null // Reset this for good measure.
|
2018-05-10 02:23:37 +00:00
|
|
|
loginUsername.value = ''
|
|
|
|
loginPassword.value = ''
|
2018-05-30 01:47:55 +00:00
|
|
|
$('.circle-loader').toggleClass('load-complete')
|
|
|
|
$('.checkmark').toggle()
|
2018-05-10 02:23:37 +00:00
|
|
|
loginLoading(false)
|
2019-04-08 03:33:40 +00:00
|
|
|
loginButton.innerHTML = loginButton.innerHTML.replace(Lang.queryJS('login.success'), Lang.queryJS('login.login'))
|
2018-05-10 02:23:37 +00:00
|
|
|
formDisabled(false)
|
2018-04-25 21:06:10 +00:00
|
|
|
})
|
|
|
|
}, 1000)
|
2022-02-06 23:23:44 +00:00
|
|
|
}).catch((displayableError) => {
|
2018-04-25 21:06:10 +00:00
|
|
|
loginLoading(false)
|
2022-02-12 00:51:28 +00:00
|
|
|
|
|
|
|
let actualDisplayableError
|
|
|
|
if(isDisplayableError(displayableError)) {
|
|
|
|
msftLoginLogger.error('Error while logging in.', displayableError)
|
|
|
|
actualDisplayableError = displayableError
|
|
|
|
} else {
|
|
|
|
// Uh oh.
|
|
|
|
msftLoginLogger.error('Unhandled error during login.', displayableError)
|
2023-10-05 19:26:32 +00:00
|
|
|
actualDisplayableError = Lang.queryJS('login.error.unknown')
|
2022-02-12 00:51:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
setOverlayContent(actualDisplayableError.title, actualDisplayableError.desc, Lang.queryJS('login.tryAgain'))
|
2018-04-25 21:06:10 +00:00
|
|
|
setOverlayHandler(() => {
|
|
|
|
formDisabled(false)
|
|
|
|
toggleOverlay(false)
|
|
|
|
})
|
|
|
|
toggleOverlay(true)
|
|
|
|
})
|
|
|
|
|
|
|
|
})
|