UI system is now workig semi-decent

This commit is contained in:
Arne van Iterson 2020-05-10 15:22:45 +02:00
parent d58b37ee33
commit eca50edb93
13 changed files with 311 additions and 155 deletions

View File

@ -3,8 +3,12 @@ body {
text-align: center;
}
body div.content {
display: none;
body header h1 {
margin-bottom: 0;
}
body header h3 {
margin: 0;
}
body div.content form label {
@ -16,12 +20,17 @@ body div.content input, body div.content button {
padding: 0.25em;
}
body div.content button {
width: 50%;
}
body div.content .message {
min-width: 80%;
height: auto;
margin: 5px auto;
padding: 5px;
font-size: small;
color: white;
}
body div.content .message.info {
@ -48,4 +57,14 @@ body.light {
color: #000;
background: #fff;
}
body footer {
font-size: small;
width: 100%;
height: auto;
position: absolute;
bottom: 0;
left: 0;
text-align: center;
}
/*# sourceMappingURL=index.css.map */

View File

@ -1,6 +1,6 @@
{
"version": 3,
"mappings": "AAAA,AAAA,IAAI,CAAC;EACD,WAAW,EAAE,4BAA4B;EACzC,UAAU,EAAE,MAAM;CAwCrB;;AA1CD,AAGI,IAHA,CAGA,GAAG,AAAA,QAAQ,CAAC;EACR,OAAO,EAAE,IAAI;CA6BhB;;AAjCL,AAMY,IANR,CAGA,GAAG,AAAA,QAAQ,CAEP,IAAI,CACA,KAAK,CAAC;EACF,SAAS,EAAE,KAAK;CACnB;;AARb,AAUQ,IAVJ,CAGA,GAAG,AAAA,QAAQ,CAOP,KAAK,EAVb,IAAI,CAGA,GAAG,AAAA,QAAQ,CAOA,MAAM,CAAC;EACV,MAAM,EAAE,KAAK;EACb,OAAO,EAAE,MAAM;CAClB;;AAbT,AAcQ,IAdJ,CAGA,GAAG,AAAA,QAAQ,CAWP,QAAQ,CAAC;EACL,SAAS,EAAE,GAAG;EACd,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,QAAQ;EAChB,OAAO,EAAE,GAAG;EACZ,SAAS,EAAE,KAAK;CAanB;;AAhCT,AAoBY,IApBR,CAGA,GAAG,AAAA,QAAQ,CAWP,QAAQ,AAMH,KAAK,CAAC;EACH,MAAM,EAAE,cAAc;EACtB,UAAU,EAAE,oBAAoB;CACnC;;AAvBb,AAwBY,IAxBR,CAGA,GAAG,AAAA,QAAQ,CAWP,QAAQ,AAUH,QAAQ,CAAC;EACN,MAAM,EAAE,aAAa;EACrB,UAAU,EAAE,oBAAoB;CACnC;;AA3Bb,AA4BY,IA5BR,CAGA,GAAG,AAAA,QAAQ,CAWP,QAAQ,AAcH,QAAQ,CAAC;EACN,MAAM,EAAE,eAAe;EACvB,UAAU,EAAE,oBAAoB;CACnC;;AA/Bb,AAkCI,IAlCA,AAkCC,KAAK,CAAC;EACH,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,IAAI;CACzB;;AArCL,AAsCI,IAtCA,AAsCC,MAAM,CAAC;EACJ,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,IAAI;CACnB",
"mappings": "AAAA,AAAA,IAAI,CAAC;EACD,WAAW,EAAE,4BAA4B;EACzC,UAAU,EAAE,MAAM;CA4DrB;;AA9DD,AAIQ,IAJJ,CAGA,MAAM,CACF,EAAE,CAAC;EACC,aAAa,EAAE,CAAC;CACnB;;AANT,AAOQ,IAPJ,CAGA,MAAM,CAIF,EAAE,CAAC;EACC,MAAM,EAAE,CAAC;CACZ;;AATT,AAaY,IAbR,CAWA,GAAG,AAAA,QAAQ,CACP,IAAI,CACA,KAAK,CAAC;EACF,SAAS,EAAE,KAAK;CACnB;;AAfb,AAiBQ,IAjBJ,CAWA,GAAG,AAAA,QAAQ,CAMP,KAAK,EAjBb,IAAI,CAWA,GAAG,AAAA,QAAQ,CAMA,MAAM,CAAC;EACV,MAAM,EAAE,KAAK;EACb,OAAO,EAAE,MAAM;CAClB;;AApBT,AAqBQ,IArBJ,CAWA,GAAG,AAAA,QAAQ,CAUP,MAAM,CAAC;EACH,KAAK,EAAE,GAAG;CACb;;AAvBT,AAwBQ,IAxBJ,CAWA,GAAG,AAAA,QAAQ,CAaP,QAAQ,CAAC;EACL,SAAS,EAAE,GAAG;EACd,MAAM,EAAE,IAAI;EACZ,MAAM,EAAE,QAAQ;EAChB,OAAO,EAAE,GAAG;EACZ,SAAS,EAAE,KAAK;EAChB,KAAK,EAAE,KAAK;CAaf;;AA3CT,AA+BY,IA/BR,CAWA,GAAG,AAAA,QAAQ,CAaP,QAAQ,AAOH,KAAK,CAAC;EACH,MAAM,EAAE,cAAc;EACtB,UAAU,EAAE,oBAAoB;CACnC;;AAlCb,AAmCY,IAnCR,CAWA,GAAG,AAAA,QAAQ,CAaP,QAAQ,AAWH,QAAQ,CAAC;EACN,MAAM,EAAE,aAAa;EACrB,UAAU,EAAE,oBAAoB;CACnC;;AAtCb,AAuCY,IAvCR,CAWA,GAAG,AAAA,QAAQ,CAaP,QAAQ,AAeH,QAAQ,CAAC;EACN,MAAM,EAAE,eAAe;EACvB,UAAU,EAAE,oBAAoB;CACnC;;AA1Cb,AA6CI,IA7CA,AA6CC,KAAK,CAAC;EACH,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,IAAI;CACzB;;AAhDL,AAiDI,IAjDA,AAiDC,MAAM,CAAC;EACJ,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,IAAI;CACnB;;AApDL,AAqDI,IArDA,CAqDA,MAAM,CAAC;EACH,SAAS,EAAE,KAAK;EAChB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,QAAQ,EAAE,QAAQ;EAClB,MAAM,EAAE,CAAC;EACT,IAAI,EAAE,CAAC;EACP,UAAU,EAAE,MAAM;CACrB",
"sources": [
"index.scss"
],

View File

@ -1,8 +1,15 @@
body {
font-family: Arial, Helvetica, sans-serif;
text-align: center;
header {
h1 {
margin-bottom: 0;
}
h3 {
margin: 0;
}
}
div.content {
display: none;
form {
label {
font-size: small;
@ -12,12 +19,16 @@ body {
margin: 0.5em;
padding: 0.25em;
}
button {
width: 50%;
}
.message {
min-width: 80%;
height: auto;
margin: 5px auto;
padding: 5px;
font-size: small;
color: white;
&.info {
border: 1px solid blue;
background: rgba(0, 0, 255, 0.5);
@ -40,4 +51,13 @@ body {
color: #000;
background: #fff;
}
footer {
font-size: small;
width: 100%;
height: auto;
position: absolute;
bottom: 0;
left: 0;
text-align: center;
}
}

View File

@ -1 +1 @@
{"theme":"dark","user":"","password":""}
{"theme":"dark","user":"arne.v.iterson@hotmail.nl","password":""}

View File

@ -3,20 +3,17 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SkinSwitcher</title>
<link rel="stylesheet" href="../css/index.css">
<title>{{ title }}</title>
<link rel="stylesheet" href="{{ css }}">
</head>
<body>
<h1>⇄<br>SkinSwitcher</h1>
<body class="{{ theme }}">
<header>
<h1>{{ header }}</h1>
<h3>Login to Minecraft</h3>
</header>
<div class="content" id="mainMenu">
<button id="button_current">Current Skin</button><br>
<button id="button_upload">Upload Skin</button><br>
<button id="button_random">Random Skin</button><br>
<button id="button_delete">Logout</button>
</div>
<div class="content" id="authForm">
<div class="content">
<p class="message"></p>
<form action="#">
<label for="user">Username or E-mail</label><br>
<input type="text" id="user" placeholder="Username or E-mail" required><br>
@ -31,20 +28,12 @@
<button type="submit">Submit</button>
</form>
</div>
</div>
<div class="content" id="skinCurrent">
<!-- Content here -->
</div>
<script src="../src/auth.js"></script>
<div class="content" id="skinUpload">
<!-- Content here -->
</div>
<div class="content" id="loader">
<p class="message info">Loading...<br>Please wait</p>
</div>
<script src="../src/index.js"></script>
<footer>
{{ footer }}
</footer>
</body>
</html>

29
html/main.hbs Normal file
View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
<link rel="stylesheet" href="{{ css }}">
</head>
<body class="{{ theme }}">
<header>
<h1>{{ header }}</h1>
<h3>Main menu</h3>
</header>
<div class="content">
<p class="message success"></p>
<button id="current">Current Skin</button><br>
<button id="upload">Upload Skin</button><br>
<button id="random">Random Skin</button><br>
<button id="logout">Logout</button>
</div>
<script src="../src/main.js"></script>
<footer>
{{ footer }}
</footer>
</body>
</html>

28
main.js
View File

@ -22,26 +22,48 @@ function createWindow () {
});
// and load the index.html of the app.
win.loadFile(path.join("html/index.html"));
win.loadFile(path.join("html/auth.hbs"));
// Open the DevTools.
if (process.env.NODE_ENV === "dev") win.webContents.openDevTools();
}
// Load previous credentials and settings
var authData = JSON.parse(fs.readFileSync("./data/data.json"));
// Define handlebars with loaded settings
require("electron-handlebars")({
css: "../css/index.css",
title: "SkinSwitcher",
theme: authData.theme,
header: "⇄ SkinSwitcher",
footer: "Made by Hecc-inc."
});
// Respond to renderer requests
ipcMain.on("getAuth", (event) => {
event.returnValue = authData;
});
ipcMain.on("setAuth", (event, data) => {
if (data != authData) {
// TODO: The app reloads causing a loop when fs is completed both in async and sync mode
//fs.writeFileSync("./data/data.json", JSON.stringify(data));
fs.writeFileSync("./data/data.json", JSON.stringify(data));
}
event.returnValue = true;
});
// Create session variables for uuid storage
var session = {};
ipcMain.on("getSession", (event) => {
event.returnValue = session;
});
ipcMain.on("setSession", (event, data) => {
session = data;
event.returnValue = true;
});
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.

72
package-lock.json generated
View File

@ -235,6 +235,20 @@
"color-convert": "^1.9.0"
}
},
"any-pify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/any-pify/-/any-pify-2.0.0.tgz",
"integrity": "sha1-b1SBH2KHJmXUJulmMXPZDJRyDs8=",
"requires": {
"any-promise": "^1.3.0",
"pify": "^3.0.0"
}
},
"any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
"integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
},
"anymatch": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz",
@ -727,6 +741,12 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
},
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"optional": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -996,6 +1016,24 @@
}
}
},
"electron-handlebars": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/electron-handlebars/-/electron-handlebars-2.0.0.tgz",
"integrity": "sha1-6iFH33MwG6BHekXgvePjE+PrpU8=",
"requires": {
"any-pify": "^2.0.0",
"handlebars": "^4.0.5",
"lodash": "^4.15.0",
"mime": "^1.3.4"
},
"dependencies": {
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
}
}
},
"electron-publish": {
"version": "22.6.0",
"resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-22.6.0.tgz",
@ -1475,6 +1513,18 @@
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw=="
},
"handlebars": {
"version": "4.7.6",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz",
"integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==",
"requires": {
"minimist": "^1.2.5",
"neo-async": "^2.6.0",
"source-map": "^0.6.1",
"uglify-js": "^3.1.4",
"wordwrap": "^1.0.0"
}
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@ -1913,6 +1963,11 @@
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
},
"neo-async": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz",
"integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw=="
},
"normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@ -2081,8 +2136,7 @@
"pify": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"optional": true
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY="
},
"pngjs": {
"version": "5.0.0",
@ -2634,6 +2688,15 @@
"is-typedarray": "^1.0.0"
}
},
"uglify-js": {
"version": "3.9.2",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.2.tgz",
"integrity": "sha512-zGVwKslUAD/EeqOrD1nQaBmXIHl1Vw371we8cvS8I6mYK9rmgX5tv8AAeJdfsQ3Kk5mGax2SVV/AizxdNGhl7Q==",
"optional": true,
"requires": {
"commander": "~2.20.3"
}
},
"unique-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz",
@ -2779,6 +2842,11 @@
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
},
"wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
},
"wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",

View File

@ -20,6 +20,7 @@
"cross-env": "^7.0.2",
"electron": "^8.2.5",
"electron-builder": "^22.6.0",
"electron-handlebars": "^2.0.0",
"electron-reload": "^1.5.0",
"eslint": "^7.0.0",
"pngjs": "^5.0.0"

72
src/auth.js Normal file
View File

@ -0,0 +1,72 @@
/* eslint-disable no-unused-vars */
const { ipcRenderer, remote } = require("electron");
const axios = require("axios").default;
const path = require("path");
// Check if a session already exists
var session = ipcRenderer.sendSync("getSession");
if (session.accessToken) {
console.log("Session does exist, go to main");
remote.getCurrentWindow().loadURL(path.join(`file://${__dirname}/main.hbs`));
} else {
console.log("Session does not exist, continue");
}
// Read auth data from storage and define variables
var authData = ipcRenderer.sendSync("getAuth");
var save = true;
async function authenticate(user, password) {
var payload = {
"agent": {
"name": "Minecraft",
"version": 1
},
"username": user,
"password": password
};
axios({
method: "POST",
url: "https://authserver.mojang.com/authenticate",
data: payload,
}).then((data) => {
console.log("Login successfull");
session = data.data;
// Save username (& password) for future login
authData.user = user;
authData.password = (save) ? password : "";
if (ipcRenderer.sendSync("setAuth", authData)) {
if (ipcRenderer.sendSync("setSession", session)) {
remote.getCurrentWindow().loadURL(path.join(`file://${__dirname}/main.hbs`));
}
}
}).catch((data) => {
console.log("Login failure");
console.log(data.response);
const msg = document.querySelectorAll("div.content > p.message")[0];
msg.classList.add("warning");
msg.innerHTML = data.response.data.errorMessage;
});
}
// Get access token from Mojang Authserver
if (authData.password == "") {
// Display auth screen when no password data is found
const form = document.querySelectorAll("div.content > form")[0];
form.querySelectorAll("input#user")[0].value = authData.user;
// Listen for form submit
form.addEventListener("submit", function(e) {
e.preventDefault();
authData.user = form.querySelectorAll("input#user")[0].value;
authData.password = form.querySelectorAll("input#password")[0].value;
save = form.querySelectorAll("input#save")[0].checked;
authenticate(authData.user, authData.password);
});
} else {
authenticate(authData.user, authData.password);
}

17
src/change.js Normal file
View File

@ -0,0 +1,17 @@
//fs.createReadStream("../data/in.png")
// .pipe(
// new PNG({
// filterType: 4,
// })
// )
// .on("parsed", (image) => {
// axios({
// method: "PUT",
// url: `https://api.mojang.com/user/profile/${data.data.selectedProfile.id}/skin`,
// data: {
// model: "",
// file: image
// },
// headers: {"Authorization": "Bearer " + data.data.accessToken}
// }).catch(console.log);
// });

View File

@ -1,120 +0,0 @@
/* eslint-disable no-unused-vars */
const { ipcRenderer } = require("electron");
const axios = require("axios").default;
const fs = require("fs");
const { PNG } = require("pngjs");
// Read auth data from storage and define variables
var authData = ipcRenderer.sendSync("getAuth");
var token;
var save = true;
// Set theme
document.body.classList.add(authData.theme);
// Function for easy switching between views
function setContent(id, message) {
document.querySelectorAll("div.content").forEach((element) => {
element.style.display = "none";
});
const element = document.querySelectorAll(`div.content#${id}`)[0];
if (message) {
var msg;
if (element.firstElementChild.classList.contains("message")) {
msg = element.firstElementChild;
} else {
msg = document.createElement("p");
}
msg.classList = `message ${message.type}`;
msg.innerHTML = message.text;
element.prepend(msg);
}
element.style.display = "block";
}
setContent("loader");
async function authenticate(user, password) {
var payload = {
"agent": {
"name": "Minecraft",
"version": 1
},
"username": user,
"password": password
};
axios({
method: "POST",
url: "https://authserver.mojang.com/authenticate",
data: payload,
}).then((data) => {
console.log("Login successfull");
token = data.data;
// Save username (& password) for future login
authData.user = user;
authData.password = (save) ? password : "";
if (ipcRenderer.sendSync("setAuth", authData)) {
setContent(
"mainMenu",
{
type: "success",
text: `Logged in as ${data.data.selectedProfile.name}`
}
);
}
}).catch((data) => {
console.log("Login failure");
console.log(data.response);
setContent(
"authForm",
{
type: "warning",
text: `Login failed<br>${data.response.data.errorMessage}`
}
);
});
}
// Get access token from Mojang Authserver
if (authData.password == "") {
// Display auth screen when no password data is found
const form = document.querySelectorAll("div.content#authForm")[0];
form.querySelectorAll("input#user")[0].value = authData.user;
setContent("authForm");
// Listen for form submit
form.addEventListener("submit", function(e) {
e.preventDefault();
authData.user = form.querySelectorAll("input#user")[0].value;
authData.password = form.querySelectorAll("input#password")[0].value;
save = form.querySelectorAll("input#save")[0].checked;
setContent("loader");
authenticate(authData.user, authData.password);
});
} else {
authenticate(authData.user, authData.password);
}
//fs.createReadStream("../data/in.png")
// .pipe(
// new PNG({
// filterType: 4,
// })
// )
// .on("parsed", (image) => {
// axios({
// method: "PUT",
// url: `https://api.mojang.com/user/profile/${data.data.selectedProfile.id}/skin`,
// data: {
// model: "",
// file: image
// },
// headers: {"Authorization": "Bearer " + data.data.accessToken}
// }).catch(console.log);
// });

39
src/main.js Normal file
View File

@ -0,0 +1,39 @@
/* eslint-disable no-unused-vars */
const { ipcRenderer, remote } = require("electron");
const axios = require("axios").default;
const path = require("path");
const session = ipcRenderer.sendSync("getSession");
if (!session.accessToken) {
console.log("Session does not exist, return to auth");
remote.getCurrentWindow().loadURL(path.join(`file://${__dirname}/auth.hbs`));
} else {
console.log("Session does exist, continue");
}
const msg = document.querySelectorAll("div.content > p.message")[0];
msg.classList.add("success");
msg.innerHTML = `Logged in as ${session.selectedProfile.name}`;
document.querySelectorAll("div.content > button#current")[0].addEventListener("click", (e) => {
console.log("Clicked current button");
});
document.querySelectorAll("div.content > button#upload")[0].addEventListener("click", (e) => {
console.log("Clicked upload button");
});
document.querySelectorAll("div.content > button#random")[0].addEventListener("click", (e) => {
console.log("Clicked random button");
});
document.querySelectorAll("div.content > button#logout")[0].addEventListener("click", (e) => {
console.log("Clicked logout button");
if (ipcRenderer.sendSync("setSession", {})) {
var authData = ipcRenderer.sendSync("getAuth");
authData.password = "";
if (ipcRenderer.sendSync("setAuth", authData)) {
remote.getCurrentWindow().loadURL(path.join(`file://${__dirname}/auth.hbs`));
}
}
});