Selaa lähdekoodia

Added mojang account validation UI.

Other minor fixes included. Bumped version from dev to alpha. Testing to begin soon.
Daniel Scalzi 7 vuotta sitten
vanhempi
sitoutus
f1a98f2d45

+ 70 - 18
app/assets/css/launcher.css

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

+ 16 - 0
app/assets/js/configmanager.js

@@ -238,6 +238,22 @@ exports.getSelectedAccount = function(){
     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
 
 // Java Settings

+ 0 - 1
app/assets/js/scripts/landing.js

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

+ 6 - 2
app/assets/js/scripts/login.js

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

+ 78 - 2
app/assets/js/scripts/overlay.js

@@ -109,11 +109,16 @@ document.addEventListener('keydown', (e) => {
         } else if(e.key === 'Enter'){
             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', () => {
     const listings = document.getElementsByClassName('serverListing')
     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.
     if(listings.length > 0){
         ConfigManager.setSelectedServer(listings[0].getAttribute('servid'))
+        ConfigManager.save()
         updateSelectedServer()
         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.
 document.getElementById('serverSelectCancel').addEventListener('click', () => {
     toggleOverlay(false)
 })
 
+document.getElementById('accountSelectCancel').addEventListener('click', () => {
+    $('#accountSelectContent').fadeOut(250, () => {
+        $('#overlayContent').fadeIn(250)
+    })
+})
+
 function setServerListingHandlers(){
     const listings = Array.from(document.getElementsByClassName('serverListing'))
     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(){
     const distro = AssetGuard.getDistributionData()
     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(){
     populateServerListings()
     setServerListingHandlers()
+}
+
+function prepareAccountSelectionList(){
+    populateAccountListings()
+    setAccountListingHandlers()
 }

+ 98 - 1
app/assets/js/scripts/uibinder.js

@@ -4,12 +4,54 @@
  */
 // Requirements
 const path          = require('path')
+const AuthManager   = require('./assets/js/authmanager.js')
 const {AssetGuard}  = require('./assets/js/assetguard.js')
 const ConfigManager = require('./assets/js/configmanager.js')
 
 let rscShouldLoad = 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(){
     updateSelectedServer(AssetGuard.getServerById(ConfigManager.getSelectedServer()).name)
     refreshServerStatus()
@@ -18,6 +60,8 @@ function showMainUI(){
         document.body.style.backgroundImage = `url('assets/images/backgrounds/${document.body.getAttribute('bkid')}.jpg')`
         $('#main').show()
 
+        //validateSelectedAccount()
+
         if(ConfigManager.isFirstLaunch()){
             $('#welcomeContainer').fadeIn(1000)
         } else {
@@ -25,7 +69,7 @@ function showMainUI(){
         }
 
         setTimeout(() => {
-            $('#loadingContainer').fadeOut(750, () => {
+            $('#loadingContainer').fadeOut(500, () => {
                 $('#loadSpinnerImage').removeClass('rotating')
             })
         }, 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
 document.addEventListener('readystatechange', function(){
 

+ 1 - 3
app/assets/js/scripts/welcome.js

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

+ 2 - 2
app/login.ejs

@@ -2,7 +2,7 @@
     <div id="loginContent">
         <form id="loginForm">
             <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">
                 <svg id="profileSVG" class="loginSVG" viewBox="40 37 65.36 61.43">
                     <g>
@@ -10,7 +10,7 @@
                     </g>
                 </svg>
                 <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 class="loginFieldContainer">
                 <svg id="lockSVG" class="loginSVG" viewBox="40 32 60.36 70.43">

+ 22 - 0
app/overlay.ejs

@@ -13,6 +13,28 @@
             </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">
         <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>

+ 1 - 1
package-lock.json

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

+ 1 - 1
package.json

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