Added mojang account validation UI.

Other minor fixes included. Bumped version from dev to alpha. Testing to begin soon.
This commit is contained in:
Daniel Scalzi 2018-05-09 22:23:37 -04:00
parent 15a83a7736
commit f1a98f2d45
No known key found for this signature in database
GPG Key ID: 5CA2F145B63535F9
11 changed files with 295 additions and 31 deletions

View File

@ -395,6 +395,7 @@ p {
height: 100%; height: 100%;
width: 100%; width: 100%;
transition: filter 0.25s ease; transition: filter 0.25s ease;
background: rgba(0, 0, 0, 0.50);
} }
/* Login content wrapper. */ /* Login content wrapper. */
@ -1790,11 +1791,12 @@ p {
} }
/* * * /* * *
* Overlay View (Server Selection Content) * Overlay View (Server + Account Selection Content)
* * */ * * */
/* Server selection content container. */ /* Server selection content container. */
#serverSelectContent { #serverSelectContent,
#accountSelectContent {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
@ -1803,7 +1805,8 @@ p {
} }
/* Server selection header. */ /* Server selection header. */
#serverSelectHeader { #serverSelectHeader,
#accountSelectHeader {
font-family: 'Avenir Medium'; font-family: 'Avenir Medium';
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
@ -1812,7 +1815,8 @@ p {
} }
/* Wrapper div for the list of available servers. */ /* Wrapper div for the list of available servers. */
#serverSelectList { #serverSelectList,
#accountSelectList {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@ -1822,17 +1826,21 @@ p {
} }
/* Scrollable div which lists the available servers. */ /* Scrollable div which lists the available servers. */
#serverSelectListScrollable { #serverSelectListScrollable,
#accountSelectListScrollable {
padding: 0px 5px; padding: 0px 5px;
overflow-y: scroll; overflow-y: scroll;
} }
#serverSelectListScrollable::-webkit-scrollbar { #serverSelectListScrollable::-webkit-scrollbar,
#accountSelectListScrollable::-webkit-scrollbar {
width: 2px; width: 2px;
} }
#serverSelectListScrollable::-webkit-scrollbar-track { #serverSelectListScrollable::-webkit-scrollbar-track,
#accountSelectListScrollable::-webkit-scrollbar-track {
display: none; display: none;
} }
#serverSelectListScrollable::-webkit-scrollbar-thumb { #serverSelectListScrollable::-webkit-scrollbar-thumb,
#accountSelectListScrollable::-webkit-scrollbar-thumb {
border-radius: 10px; border-radius: 10px;
box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.50); box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.50);
} }
@ -1862,14 +1870,49 @@ p {
opacity: 1.0; opacity: 1.0;
} }
.accountListing {
color: white;
border: 1px solid rgba(170, 170, 170, 0.5);
border-radius: 4px;
padding: 5px 45px;
width: 250px;
display: flex;
justify-content: flex-start;
align-items: center;
opacity: 0.6;
transition: 0.25s ease;
cursor: pointer;
position: relative;
background: rgba(255, 255, 255, 0.25);
}
.accountListing[selected] {
cursor: default;
opacity: 1.0;
}
.accountListing:hover,
.accountListing:focus {
outline: none;
opacity: 1.0;
}
.accountListingName {
display: flex;
height: 100%;
width: 100%;
padding-left: 10px;
}
/* Add spacing between server listings. */ /* Add spacing between server listings. */
#serverSelectListScrollable > .serverListing:not(:first-child):not(:last-child) { #serverSelectListScrollable > .serverListing:not(:first-child):not(:last-child),
#accountSelectListScrollable > .accountListing:not(:first-child):not(:last-child) {
margin: 5px 0px; margin: 5px 0px;
} }
#serverSelectListScrollable > .serverListing:first-child { #serverSelectListScrollable > .serverListing:first-child,
#accountSelectListScrollable > .accountListing:first-child {
margin-bottom: 5px; margin-bottom: 5px;
} }
#serverSelectListScrollable > .serverListing:last-child { #serverSelectListScrollable > .serverListing:last-child,
#accountSelectListScrollable > .accountListing:last-child {
margin-top: 5px; margin-top: 5px;
} }
@ -1980,7 +2023,8 @@ p {
} }
/* Content container which contains the server select actions. */ /* Content container which contains the server select actions. */
#serverSelectActions { #serverSelectActions,
#accountSelectActions {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
@ -1989,7 +2033,8 @@ p {
} }
/* Server selection confirm button styles. */ /* Server selection confirm button styles. */
#serverSelectConfirm { #serverSelectConfirm,
#accountSelectConfirm {
background: none; background: none;
border: 1px solid #ffffff; border: 1px solid #ffffff;
color: white; color: white;
@ -2002,17 +2047,21 @@ p {
min-height: 20.67px; min-height: 20.67px;
} }
#serverSelectConfirm:hover, #serverSelectConfirm:hover,
#serverSelectConfirm:focus { #serverSelectConfirm:focus,
#accountSelectConfirm:hover,
#accountSelectConfirm:focus {
box-shadow: 0px 0px 10px 0px #fff; box-shadow: 0px 0px 10px 0px #fff;
outline: none; outline: none;
} }
#serverSelectConfirm:active { #serverSelectConfirm:active,
#accountSelectConfirm:active {
border-color: rgba(255, 255, 255, 0.75); border-color: rgba(255, 255, 255, 0.75);
color: rgba(255, 255, 255, 0.75); color: rgba(255, 255, 255, 0.75);
} }
/* Server selection cancel button styles. */ /* Server selection cancel button styles. */
#serverSelectCancel { #serverSelectCancel,
#accountSelectCancel {
font-family: 'Avenir Book'; font-family: 'Avenir Book';
font-weight: bold; font-weight: bold;
font-size: 10px; font-size: 10px;
@ -2026,10 +2075,13 @@ p {
cursor: pointer; cursor: pointer;
} }
#serverSelectCancel:hover, #serverSelectCancel:hover,
#serverSelectCancel:focus { #serverSelectCancel:focus,
#accountSelectCancel:hover,
#accountSelectCancel:focus {
color: rgba(255, 255, 255, 0.75); color: rgba(255, 255, 255, 0.75);
} }
#serverSelectCancel:active { #serverSelectCancel:active,
#accountSelectCancel:active {
color: rgba(165, 165, 165, 0.75); color: rgba(165, 165, 165, 0.75);
} }

View File

@ -238,6 +238,22 @@ exports.getSelectedAccount = function(){
return config.authenticationDatabase[config.selectedAccount] return config.authenticationDatabase[config.selectedAccount]
} }
/**
* Set the selected authenticated account.
*
* @param {string} uuid The UUID of the account which is to be set
* as the selected account.
*
* @returns {Object} The selected authenticated account.
*/
exports.setSelectedAccount = function(uuid){
const authAcc = config.authenticationDatabase[uuid]
if(authAcc != null) {
config.selectedAccount = uuid
}
return authAcc
}
// User Configurable Settings // User Configurable Settings
// Java Settings // Java Settings

View File

@ -6,7 +6,6 @@ const cp = require('child_process')
const {URL} = require('url') const {URL} = require('url')
// Internal Requirements // Internal Requirements
const AuthManager = require('./assets/js/authmanager.js')
const DiscordWrapper = require('./assets/js/discordwrapper.js') const DiscordWrapper = require('./assets/js/discordwrapper.js')
const Mojang = require('./assets/js/mojang.js') const Mojang = require('./assets/js/mojang.js')
const ProcessBuilder = require('./assets/js/processbuilder.js') const ProcessBuilder = require('./assets/js/processbuilder.js')

View File

@ -233,8 +233,12 @@ loginButton.addEventListener('click', () => {
$('.checkmark').toggle() $('.checkmark').toggle()
//console.log(value) //console.log(value)
setTimeout(() => { setTimeout(() => {
$('#loginContainer').fadeOut(500, () => { switchView(VIEWS.login, VIEWS.landing, 500, 500, () => {
$('#landingContainer').fadeIn(500) loginUsername.value = ''
loginPassword.value = ''
loginLoading(false)
loginButton.innerHTML = loginButton.innerHTML.replace('SUCCESS', 'LOGIN')
formDisabled(false)
}) })
}, 1000) }, 1000)
}).catch((err) => { }).catch((err) => {

View File

@ -109,11 +109,16 @@ document.addEventListener('keydown', (e) => {
} else if(e.key === 'Enter'){ } else if(e.key === 'Enter'){
document.getElementById('serverSelectConfirm').click() document.getElementById('serverSelectConfirm').click()
} }
} else if(document.getElementById('accountSelectContent').style.display !== 'none'){
console.debug('ServSelLi Keydown Called:', document.getElementById('accountSelectContent').style.display)
if(e.key === 'Escape'){
document.getElementById('accountSelectCancel').click()
} else if(e.key === 'Enter'){
document.getElementById('accountSelectConfirm').click()
}
} }
}) })
document.getElementById('serverSelectActions').onsubmit = () => { return false }
document.getElementById('serverSelectConfirm').addEventListener('click', () => { document.getElementById('serverSelectConfirm').addEventListener('click', () => {
const listings = document.getElementsByClassName('serverListing') const listings = document.getElementsByClassName('serverListing')
for(let i=0; i<listings.length; i++){ for(let i=0; i<listings.length; i++){
@ -131,16 +136,45 @@ document.getElementById('serverSelectConfirm').addEventListener('click', () => {
// None are selected? Not possible right? Meh, handle it. // None are selected? Not possible right? Meh, handle it.
if(listings.length > 0){ if(listings.length > 0){
ConfigManager.setSelectedServer(listings[0].getAttribute('servid')) ConfigManager.setSelectedServer(listings[0].getAttribute('servid'))
ConfigManager.save()
updateSelectedServer() updateSelectedServer()
toggleOverlay(false) toggleOverlay(false)
} }
}) })
document.getElementById('accountSelectConfirm').addEventListener('click', () => {
const listings = document.getElementsByClassName('accountListing')
for(let i=0; i<listings.length; i++){
if(listings[i].hasAttribute('selected')){
const authAcc = ConfigManager.setSelectedAccount(listings[i].getAttribute('uuid'))
ConfigManager.save()
updateSelectedAccount(authAcc)
toggleOverlay(false)
validateSelectedAccount()
return
}
}
// None are selected? Not possible right? Meh, handle it.
if(listings.length > 0){
const authAcc = ConfigManager.setSelectedAccount(listings[0].getAttribute('uuid'))
ConfigManager.save()
updateSelectedAccount(authAcc)
toggleOverlay(false)
validateSelectedAccount()
}
})
// Bind server select cancel button. // Bind server select cancel button.
document.getElementById('serverSelectCancel').addEventListener('click', () => { document.getElementById('serverSelectCancel').addEventListener('click', () => {
toggleOverlay(false) toggleOverlay(false)
}) })
document.getElementById('accountSelectCancel').addEventListener('click', () => {
$('#accountSelectContent').fadeOut(250, () => {
$('#overlayContent').fadeIn(250)
})
})
function setServerListingHandlers(){ function setServerListingHandlers(){
const listings = Array.from(document.getElementsByClassName('serverListing')) const listings = Array.from(document.getElementsByClassName('serverListing'))
listings.map((val) => { listings.map((val) => {
@ -160,6 +194,25 @@ function setServerListingHandlers(){
}) })
} }
function setAccountListingHandlers(){
const listings = Array.from(document.getElementsByClassName('accountListing'))
listings.map((val) => {
val.onclick = e => {
if(val.hasAttribute('selected')){
return
}
const cListings = document.getElementsByClassName('accountListing')
for(let i=0; i<cListings.length; i++){
if(cListings[i].hasAttribute('selected')){
cListings[i].removeAttribute('selected')
}
}
val.setAttribute('selected', '')
document.activeElement.blur()
}
})
}
function populateServerListings(){ function populateServerListings(){
const distro = AssetGuard.getDistributionData() const distro = AssetGuard.getDistributionData()
const giaSel = ConfigManager.getSelectedServer() const giaSel = ConfigManager.getSelectedServer()
@ -192,7 +245,30 @@ function populateServerListings(){
} }
function populateAccountListings(){
const accountsObj = ConfigManager.getAuthAccounts()
const accounts = Array.from(Object.keys(accountsObj), v=>accountsObj[v]);
const selectedUUID = ConfigManager.getSelectedAccount().uuid
let htmlString = ``
for(let i=0; i<accounts.length; i++){
if(accounts[i].uuid === selectedUUID) {
continue
}
htmlString += `<button class="accountListing" uuid="${accounts[i].uuid}" ${i===0 ? 'selected' : ''}>
<img src="https://crafatar.com/renders/head/${accounts[i].uuid}?scale=2&default=MHF_Steve&overlay">
<div class="accountListingName">${accounts[i].displayName}</div>
</button>`
}
document.getElementById('accountSelectListScrollable').innerHTML = htmlString
}
function prepareServerSelectionList(){ function prepareServerSelectionList(){
populateServerListings() populateServerListings()
setServerListingHandlers() setServerListingHandlers()
}
function prepareAccountSelectionList(){
populateAccountListings()
setAccountListingHandlers()
} }

View File

@ -4,12 +4,54 @@
*/ */
// Requirements // Requirements
const path = require('path') const path = require('path')
const AuthManager = require('./assets/js/authmanager.js')
const {AssetGuard} = require('./assets/js/assetguard.js') const {AssetGuard} = require('./assets/js/assetguard.js')
const ConfigManager = require('./assets/js/configmanager.js') const ConfigManager = require('./assets/js/configmanager.js')
let rscShouldLoad = false let rscShouldLoad = false
let fatalStartupError = false let fatalStartupError = false
// Mapping of each view to their container IDs.
const VIEWS = {
landing: 'landingContainer',
login: 'loginContainer',
welcome: 'welcomeContainer'
}
// The currently shown view container.
let currentView = VIEWS.landing
/**
* Switch launcher views.
*
* @param {string} current The ID of the current view container.
* @param {*} next The ID of the next view container.
* @param {*} currentFadeTime Optional. The fade out time for the current view.
* @param {*} nextFadeTime Optional. The fade in time for the next view.
* @param {*} onCurrentFade Optional. Callback function to execute when the current
* view fades out.
* @param {*} onNextFade Optional. Callback function to execute when the next view
* fades in.
*/
function switchView(current, next, currentFadeTime = 500, nextFadeTime = 500, onCurrentFade = () => {}, onNextFade = () => {}){
currentView = current
$(`#${current}`).fadeOut(currentFadeTime, () => {
onCurrentFade()
$(`#${next}`).fadeIn(nextFadeTime, () => {
onNextFade()
})
})
}
/**
* Get the currently shown view container.
*
* @returns {string} The currently shown view container.
*/
function getCurrentView(){
return currentView
}
function showMainUI(){ function showMainUI(){
updateSelectedServer(AssetGuard.getServerById(ConfigManager.getSelectedServer()).name) updateSelectedServer(AssetGuard.getServerById(ConfigManager.getSelectedServer()).name)
refreshServerStatus() refreshServerStatus()
@ -18,6 +60,8 @@ function showMainUI(){
document.body.style.backgroundImage = `url('assets/images/backgrounds/${document.body.getAttribute('bkid')}.jpg')` document.body.style.backgroundImage = `url('assets/images/backgrounds/${document.body.getAttribute('bkid')}.jpg')`
$('#main').show() $('#main').show()
//validateSelectedAccount()
if(ConfigManager.isFirstLaunch()){ if(ConfigManager.isFirstLaunch()){
$('#welcomeContainer').fadeIn(1000) $('#welcomeContainer').fadeIn(1000)
} else { } else {
@ -25,7 +69,7 @@ function showMainUI(){
} }
setTimeout(() => { setTimeout(() => {
$('#loadingContainer').fadeOut(750, () => { $('#loadingContainer').fadeOut(500, () => {
$('#loadSpinnerImage').removeClass('rotating') $('#loadSpinnerImage').removeClass('rotating')
}) })
}, 500) }, 500)
@ -70,6 +114,59 @@ function refreshDistributionIndex(remote, onSuccess, onError){
} }
} }
async function validateSelectedAccount(){
const selectedAcc = ConfigManager.getSelectedAccount()
if(selectedAcc != null){
const val = await AuthManager.validateSelected()
if(!val){
const accLen = Object.keys(ConfigManager.getAuthAccounts()).length
setOverlayContent(
'Failed to Refresh Login',
`We were unable to refresh the login for <strong>${selectedAcc.displayName}</strong>. Please ${accLen > 1 ? 'select another account or ' : ''} login again.`,
'Login',
'Select Another Account'
)
setOverlayHandler(() => {
document.getElementById('loginUsername').value = selectedAcc.username
validateEmail(selectedAcc.username)
switchView(getCurrentView(), VIEWS.login)
toggleOverlay(false)
})
setDismissHandler(() => {
if(accLen > 2){
prepareAccountSelectionList()
$('#overlayContent').fadeOut(250, () => {
$('#accountSelectContent').fadeIn(250)
})
} else {
const accountsObj = ConfigManager.getAuthAccounts()
const accounts = Array.from(Object.keys(accountsObj), v=>accountsObj[v]);
const selectedUUID = ConfigManager.getSelectedAccount().uuid
for(let i=0; i<accounts.length; i++){
if(accounts[i].uuid !== selectedUUID){
setSelectedAccount(accounts[i].uuid)
toggleOverlay(false)
validateSelectedAccount()
}
}
}
})
toggleOverlay(true, accLen > 1)
} else {
return true
}
} else {
return true
}
}
function setSelectedAccount(uuid){
const authAcc = ConfigManager.setSelectedAccount(uuid)
ConfigManager.save()
updateSelectedAccount(authAcc)
//validateSelectedAccount()
}
// Synchronous Listener // Synchronous Listener
document.addEventListener('readystatechange', function(){ document.addEventListener('readystatechange', function(){

View File

@ -2,7 +2,5 @@
* Script for welcome.ejs * Script for welcome.ejs
*/ */
document.getElementById('welcomeButton').addEventListener('click', e => { document.getElementById('welcomeButton').addEventListener('click', e => {
$('#welcomeContainer').fadeOut(500, () => { switchView(VIEWS.welcome, VIEWS.login)
$('#loginContainer').fadeIn(500)
})
}) })

View File

@ -2,7 +2,7 @@
<div id="loginContent"> <div id="loginContent">
<form id="loginForm"> <form id="loginForm">
<img id="loginImageSeal" src="assets/images/WesterosSealCircle.png"/> <img id="loginImageSeal" src="assets/images/WesterosSealCircle.png"/>
<span class="loginSpan" id="loginSubheader">MEMBER LOGIN</span> <span class="loginSpan" id="loginSubheader">MINECRAFT LOGIN</span>
<div class="loginFieldContainer"> <div class="loginFieldContainer">
<svg id="profileSVG" class="loginSVG" viewBox="40 37 65.36 61.43"> <svg id="profileSVG" class="loginSVG" viewBox="40 37 65.36 61.43">
<g> <g>
@ -10,7 +10,7 @@
</g> </g>
</svg> </svg>
<span class="loginErrorSpan" id="loginEmailError">* Invalid Value</span> <span class="loginErrorSpan" id="loginEmailError">* Invalid Value</span>
<input id="loginUsername" class="loginField" type="text" placeholder="EMAIL"/> <input id="loginUsername" class="loginField" type="text" placeholder="EMAIL OR USERNAME"/>
</div> </div>
<div class="loginFieldContainer"> <div class="loginFieldContainer">
<svg id="lockSVG" class="loginSVG" viewBox="40 32 60.36 70.43"> <svg id="lockSVG" class="loginSVG" viewBox="40 32 60.36 70.43">

View File

@ -13,6 +13,28 @@
</div> </div>
</div> </div>
</div> </div>
<div id="accountSelectContent" style="display: none;">
<span id="accountSelectHeader">Select an Account</span>
<div id="accountSelectList">
<div id="accountSelectListScrollable">
<button class="accountListing" uuid="fead86af28284e4e90d4cc5b9eb3ae84">
<img src="https://crafatar.com/renders/head/fead86af28284e4e90d4cc5b9eb3ae84?scale=2&default=MHF_Steve&overlay">
<div class="accountListingName">TheKraken7</div>
</button>
<button class="accountListing" uuid="48f0a3d02ae14ca4aa0011bb8bc4f39e">
<img src="https://crafatar.com/renders/head/48f0a3d02ae14ca4aa0011bb8bc4f39e?scale=2&default=MHF_Steve&overlay">
<div class="accountListingName">iPepsiHD</div>
</button>
<!-- Accounts populated here. -->
</div>
</div>
<div id="accountSelectActions">
<button id="accountSelectConfirm" type="submit">Select</button>
<div id="accountSelectCancelWrapper">
<button id="accountSelectCancel">Cancel</button>
</div>
</div>
</div>
<div id="overlayContent"> <div id="overlayContent">
<span id="overlayTitle">Lorem Ipsum:<br>Finis Illud</span> <span id="overlayTitle">Lorem Ipsum:<br>Finis Illud</span>
<span id="overlayDesc">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud..</span> <span id="overlayDesc">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud..</span>

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "westeroscraftlauncher", "name": "westeroscraftlauncher",
"version": "0.0.1-dev", "version": "0.0.1-alpha.1",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View File

@ -1,6 +1,6 @@
{ {
"name": "westeroscraftlauncher", "name": "westeroscraftlauncher",
"version": "0.0.1-dev", "version": "0.0.1-alpha.1",
"description": "Custom modded launcher for Westeroscraft", "description": "Custom modded launcher for Westeroscraft",
"productName": "WesterosCraft Launcher", "productName": "WesterosCraft Launcher",
"main": "index.js", "main": "index.js",