allow debugging

This commit is contained in:
SpikeHD 2022-05-07 20:49:45 -07:00
parent 376171b2cf
commit b9a77ab8f1
9 changed files with 231 additions and 15 deletions

View File

@ -9,6 +9,7 @@
<script src="js/hoverEvt.js"></script> <script src="js/hoverEvt.js"></script>
<script src="js/helpers.js"></script> <script src="js/helpers.js"></script>
<script src="js/index.js"></script> <script src="js/index.js"></script>
<script src="js/debug.js"></script>
<script src="js/gcdownloader.js"></script> <script src="js/gcdownloader.js"></script>
<script src="js/onLoad.js"></script> <script src="js/onLoad.js"></script>
<script src="js/alerts.js"></script> <script src="js/alerts.js"></script>

View File

@ -6,6 +6,8 @@ function displayAlert(message, clear = 4000) {
alertText.innerText = message alertText.innerText = message
debug.log('Displaying message: ' + message)
setTimeout(() => { setTimeout(() => {
hideAlert() hideAlert()
}, clear) }, clear)
@ -15,5 +17,7 @@ function hideAlert() {
const alert = document.getElementById('alert') const alert = document.getElementById('alert')
const alertText = document.getElementById('alertText') const alertText = document.getElementById('alertText')
debug.log('Hiding alert')
alert.classList.remove('show') alert.classList.remove('show')
} }

View File

@ -2,10 +2,12 @@ let alertTimeout, alertCooldown = 3000
async function displayLoginAlert(message, type, cooldown = null) { async function displayLoginAlert(message, type, cooldown = null) {
displayAuthAlert(message, type, cooldown, 'login') displayAuthAlert(message, type, cooldown, 'login')
debug.log('Login alert: ' + message)
} }
async function displayRegisterAlert(message, type, cooldown = null) { async function displayRegisterAlert(message, type, cooldown = null) {
displayAuthAlert(message, type, cooldown, 'register') displayAuthAlert(message, type, cooldown, 'register')
debug.log('Register alert: ' + message)
} }
function displayAuthAlert(message, type, cooldown, name) { function displayAuthAlert(message, type, cooldown, name) {
@ -41,5 +43,7 @@ function displayAuthAlert(message, type, cooldown, name) {
// Disappear after cooldown // Disappear after cooldown
alertTimeout = setTimeout(() => { alertTimeout = setTimeout(() => {
elm.style.display = 'none' elm.style.display = 'none'
debug.log('Hiding auth alert')
}, cooldown || alertCooldown) }, cooldown || alertCooldown)
} }

17
resources/js/debug.js Normal file
View File

@ -0,0 +1,17 @@
const debug = {
log: async (...args) => {
const cfg = await getCfg()
if (cfg.debug) console.log('[DEBUG] ', ...args)
},
warn: async (...args) => {
const cfg = await getCfg()
if (cfg.debug) console.log('[WARNING] ', ...args)
},
error: async (...args) => {
const cfg = await getCfg()
if (cfg.debug) console.log('[ERROR] ', ...args)
}
}

View File

@ -11,6 +11,8 @@ async function setDownloadButtonsToLoading() {
devBtn.disabled = true devBtn.disabled = true
devBtn.classList.add('disabled') devBtn.classList.add('disabled')
debug.log('Set download buttons to loading')
} }
async function resetDownloadButtons() { async function resetDownloadButtons() {
@ -26,12 +28,19 @@ async function resetDownloadButtons() {
devBtn.disabled = false devBtn.disabled = false
devBtn.classList.remove('disabled') devBtn.classList.remove('disabled')
debug.log('Reset download buttons')
} }
async function downloadDataFiles(branch) { async function downloadDataFiles(branch) {
const config = await getCfg() const config = await getCfg()
if (!branch) branch = config.grasscutterBranch || 'development' if (!branch) {
debug.warn('Branch not specified')
branch = config.grasscutterBranch || 'development'
}
debug.log('Using branch: ' + branch)
setDownloadButtonsToLoading() setDownloadButtonsToLoading()
@ -41,33 +50,37 @@ async function downloadDataFiles(branch) {
.map(file => ({ path: file.path, filename: file.name })) .map(file => ({ path: file.path, filename: file.name }))
.map(o => ({ url: `https://raw.githubusercontent.com/Grasscutters/Grasscutter/${branch}/${o.path}`, filename: o.filename })) .map(o => ({ url: `https://raw.githubusercontent.com/Grasscutters/Grasscutter/${branch}/${o.path}`, filename: o.filename }))
debug.log('Downloaded data files')
// For key files // For key files
const keyFiles = await axios.get(`https://api.github.com/repos/Grasscutters/Grasscutter/contents/keys?ref=${branch}`) const keyFiles = await axios.get(`https://api.github.com/repos/Grasscutters/Grasscutter/contents/keys?ref=${branch}`)
const keyList = keyFiles.data const keyList = keyFiles.data
.map(file => ({ path: file.path, filename: file.name })) .map(file => ({ path: file.path, filename: file.name }))
.map(o => ({ url: `https://raw.githubusercontent.com/Grasscutters/Grasscutter/${branch}/${o.path}`, filename: o.filename })) .map(o => ({ url: `https://raw.githubusercontent.com/Grasscutters/Grasscutter/${branch}/${o.path}`, filename: o.filename }))
debug.log('Downloaded key files')
const serverFolderFixed = config.serverFolder.match(/.*\\|.*\//g, '')[0].replace(/\//g, '\\') const serverFolderFixed = config.serverFolder.match(/.*\\|.*\//g, '')[0].replace(/\//g, '\\')
// Ensure data and key folders exist debug.log('Server folder fixed: ' + serverFolderFixed)
console.log(config.serverFolder)
console.log(serverFolderFixed)
await Neutralino.os.execCommand(`mkdir ${serverFolderFixed}\\data`) await Neutralino.os.execCommand(`mkdir ${serverFolderFixed}\\data`)
await Neutralino.os.execCommand(`mkdir ${serverFolderFixed}\\keys`) await Neutralino.os.execCommand(`mkdir ${serverFolderFixed}\\keys`)
debug.log('Created data and keys folders')
// Download data files // Download data files
for (const o of dataList) { for (const o of dataList) {
const folder = 'data' const folder = 'data'
const e = await Neutralino.os.execCommand(`powershell Invoke-WebRequest -Uri ${o.url} -OutFile "${serverFolderFixed}\\${folder}\\${o.filename}"`) const e = await Neutralino.os.execCommand(`powershell Invoke-WebRequest -Uri ${o.url} -OutFile "${serverFolderFixed}\\${folder}\\${o.filename}"`)
console.log(e) debug.log(e.stdIn)
} }
// Download key files // Download key files
for (const o of keyList) { for (const o of keyList) {
const folder = 'keys' const folder = 'keys'
const e = await Neutralino.os.execCommand(`powershell Invoke-WebRequest -Uri ${o.url} -OutFile "${serverFolderFixed}\\${folder}\\${o.filename}"`) const e = await Neutralino.os.execCommand(`powershell Invoke-WebRequest -Uri ${o.url} -OutFile "${serverFolderFixed}\\${folder}\\${o.filename}"`)
console.log(e) debug.log(e.stdIn)
} }
// Fix buttons // Fix buttons
@ -80,9 +93,13 @@ async function downloadGC(branch) {
// Set current installation in config // Set current installation in config
config.grasscutterBranch = branch config.grasscutterBranch = branch
debug.log('Branch set to: ' + branch)
// Set gc path for people with launcher enabled // Set gc path for people with launcher enabled
config.serverFolder = `${NL_CWD}\\gc-${branch}\\grasscutter.jar` config.serverFolder = `${NL_CWD}\\gc-${branch}\\grasscutter.jar`
debug.log('Server folder automatically set to: ' + config.serverFolder)
// Enable server launcher // Enable server launcher
config.serverLaunchPanel = true config.serverLaunchPanel = true
@ -96,14 +113,20 @@ async function downloadGC(branch) {
await axios.get(artiUrl).catch(e => { await axios.get(artiUrl).catch(e => {
// Fallback link if artifacts are not being uploaded // Fallback link if artifacts are not being uploaded
debug.warn('Artifacts not available for latest, falling back...')
artiUrl = 'https://nightly.link/Grasscutters/Grasscutter/actions/runs/2284467925/Grasscutter.zip' artiUrl = 'https://nightly.link/Grasscutters/Grasscutter/actions/runs/2284467925/Grasscutter.zip'
}) })
debug.log('Artifact URL: ' + artiUrl)
// Keystore for branch (since they can differ) // Keystore for branch (since they can differ)
const keystoreUrl = `https://github.com/Grasscutters/Grasscutter/raw/${branch}/keystore.p12` const keystoreUrl = `https://github.com/Grasscutters/Grasscutter/raw/${branch}/keystore.p12`
// Run installer // Run installer
createCmdWindow(`.\\scripts\\gc_download.cmd ${artiUrl} ${keystoreUrl} ${branch}`) createCmdWindow(`.\\scripts\\gc_download.cmd ${artiUrl} ${keystoreUrl} ${branch}`)
debug.log('Created installer window')
// Display folder after saving config // Display folder after saving config
displayServerFolder() displayServerFolder()
enableServerButton() enableServerButton()
@ -114,6 +137,10 @@ async function downloadResources() {
const config = await getCfg() const config = await getCfg()
const serverFolderFixed = config.serverFolder.match(/.*\\|.*\//g, '')[0].replace(/\//g, '\\') const serverFolderFixed = config.serverFolder.match(/.*\\|.*\//g, '')[0].replace(/\//g, '\\')
debug.log('Server folder fixed: ' + serverFolderFixed)
// Dont bother with data or keys, just want straight resources // Dont bother with data or keys, just want straight resources
createCmdWindow(`.\\scripts\\resources_download.cmd "${serverFolderFixed}"`) createCmdWindow(`.\\scripts\\resources_download.cmd "${serverFolderFixed}"`)
debug.log('Created resources window')
} }

View File

@ -12,6 +12,7 @@ async function getCfg() {
serverLaunchPanel: false, serverLaunchPanel: false,
language: 'en', language: 'en',
useHttps: true, useHttps: true,
debug: true,
grasscutterBranch: '', grasscutterBranch: '',
} }
const cfgStr = await Neutralino.storage.getData('config').catch(e => { const cfgStr = await Neutralino.storage.getData('config').catch(e => {
@ -20,6 +21,8 @@ async function getCfg() {
// Show the first time notice if there is no config // Show the first time notice if there is no config
document.querySelector('#firstTimeNotice').style.display = 'block' document.querySelector('#firstTimeNotice').style.display = 'block'
debug.warn('First time opening')
}) })
const config = cfgStr ? JSON.parse(cfgStr) : defaultConf const config = cfgStr ? JSON.parse(cfgStr) : defaultConf
@ -36,8 +39,12 @@ async function getFavIps() {
const ipStr = await Neutralino.storage.getData('favorites').catch(e => { const ipStr = await Neutralino.storage.getData('favorites').catch(e => {
// The data isn't set, so this is our first time opening // The data isn't set, so this is our first time opening
Neutralino.storage.setData('favorites', JSON.stringify([])) Neutralino.storage.setData('favorites', JSON.stringify([]))
debug.warn('No favorites set')
}) })
debug.log('Favorites:', ipStr)
const ipArr = ipStr ? JSON.parse(ipStr) : [] const ipArr = ipStr ? JSON.parse(ipStr) : []
return ipArr return ipArr
@ -50,20 +57,27 @@ async function proxyIsInstalled() {
if (curDirList.find(f => f.entry === 'ext')) { if (curDirList.find(f => f.entry === 'ext')) {
const extFiles = await filesystem.readDirectory(NL_CWD + '/ext') const extFiles = await filesystem.readDirectory(NL_CWD + '/ext')
debug.log('ext/ folder exists')
if (extFiles.find(f => f.entry === 'mitmdump.exe')) { if (extFiles.find(f => f.entry === 'mitmdump.exe')) {
debug.log('mitmdump exists')
return true return true
} }
} }
debug.log('No proxy installed')
return false return false
} }
async function checkForUpdates() { async function checkForUpdates() {
const url = 'https://api.github.com/repos/Grasscutters/GrassClipper/releases/latest' const url = 'https://api.github.com/repos/Grasscutters/GrassClipper/releases/latest'
const { data } = await axios.get(url) const { data } = await axios.get(url).catch(e => debug.error('Error getting latest release'))
const latest = data.tag_name const latest = data.tag_name
debug.log('Latest release:', latest)
return latest return latest
} }
@ -72,8 +86,12 @@ async function displayUpdate() {
const versionDisplay = document.querySelector('#newestVersion') const versionDisplay = document.querySelector('#newestVersion')
const notif = document.querySelector('#downloadNotif') const notif = document.querySelector('#downloadNotif')
debug.log('Comparing versions: ' + latest + ' vs v' + NL_APPVERSION)
if (latest === `v${NL_APPVERSION}`) return if (latest === `v${NL_APPVERSION}`) return
debug.log('New version available')
versionDisplay.innerText = latest versionDisplay.innerText = latest
notif.classList.add('displayed') notif.classList.add('displayed')
@ -86,6 +104,8 @@ async function displayUpdate() {
async function openLatestDownload() { async function openLatestDownload() {
const downloadLink = 'https://github.com/Grasscutters/GrassClipper/releases/latest/' const downloadLink = 'https://github.com/Grasscutters/GrassClipper/releases/latest/'
debug.log('Opening download link: ', downloadLink)
Neutralino.os.open(downloadLink) Neutralino.os.open(downloadLink)
} }
@ -93,6 +113,8 @@ async function openGameFolder() {
const config = await getCfg() const config = await getCfg()
const folder = config.gameexe.match(/.*\\|.*\//g, '') const folder = config.gameexe.match(/.*\\|.*\//g, '')
debug.log('Opening game folder: ', folder)
if (folder.length > 0) openInExplorer(folder[0].replace(/\//g, '\\')) if (folder.length > 0) openInExplorer(folder[0].replace(/\//g, '\\'))
} }
@ -100,6 +122,8 @@ async function openGrasscutterFolder() {
const config = await getCfg() const config = await getCfg()
const folder = config.serverFolder.match(/.*\\|.*\//g, '') const folder = config.serverFolder.match(/.*\\|.*\//g, '')
debug.log('Opening grasscutter folder: ', folder)
if (folder.length > 0) openInExplorer(folder[0].replace(/\//g, '\\')) if (folder.length > 0) openInExplorer(folder[0].replace(/\//g, '\\'))
} }
@ -108,6 +132,9 @@ function hasForeignChars(str) {
let re1 = /^[\x00-\x7F]+$/g let re1 = /^[\x00-\x7F]+$/g
str = str.replace(/\s/g, '') str = str.replace(/\s/g, '')
debug.log('Checking for foreign chars in path: ', str)
debug.log('Path includes foreign chars? ', re1.test(str))
return !re1.test(str) return !re1.test(str)
} }
@ -118,8 +145,11 @@ function openDialog(title, message, negBtn = false, affirmBtn = closeDialog) {
const noBtn = document.getElementById('dialogButtonNeg') const noBtn = document.getElementById('dialogButtonNeg')
const yesBtn = document.getElementById('dialogButtonAffirm') const yesBtn = document.getElementById('dialogButtonAffirm')
debug.log('Opening dialog: ', title, message)
if (!negBtn) { if (!negBtn) {
noBtn.style.display = 'none' noBtn.style.display = 'none'
debug.log('No "no" button')
} else { } else {
noBtn.style.removeProperty('display') noBtn.style.removeProperty('display')
noBtn.onclick = () => closeDialog() noBtn.onclick = () => closeDialog()
@ -129,6 +159,7 @@ function openDialog(title, message, negBtn = false, affirmBtn = closeDialog) {
noBtn.innerText = localeObj.dialogNo || 'NO' noBtn.innerText = localeObj.dialogNo || 'NO'
yesBtn.onclick = () => { yesBtn.onclick = () => {
debug.log('Affirmative button clicked')
affirmBtn() affirmBtn()
closeDialog() closeDialog()
} }
@ -144,6 +175,8 @@ function openDialog(title, message, negBtn = false, affirmBtn = closeDialog) {
function closeDialog() { function closeDialog() {
const dialog = document.getElementById('miscDialog') const dialog = document.getElementById('miscDialog')
debug.log('Closing dialog')
dialog.style.display = 'none' dialog.style.display = 'none'
} }
@ -151,6 +184,7 @@ function closeDialog() {
* Minimize the window * Minimize the window
*/ */
function minimizeWin() { function minimizeWin() {
debug.log('Minimizing window')
Neutralino.window.minimize() Neutralino.window.minimize()
} }
@ -158,6 +192,7 @@ function minimizeWin() {
* Close the window * Close the window
*/ */
function closeWin() { function closeWin() {
debug.log('Closing window')
Neutralino.app.exit() Neutralino.app.exit()
window.close() window.close()

View File

@ -3,10 +3,12 @@ NL_CWD = NL_CWD.replace(/\//g, '\\')
let localeObj let localeObj
const filesystem = Neutralino.filesystem const filesystem = Neutralino.filesystem
const createCmdWindow = async (command) => { const createCmdWindow = async (command) => {
debug.log('Running command in new window: ' + command)
Neutralino.os.execCommand(`cmd.exe /c start "" ${command}`, { background: true }) Neutralino.os.execCommand(`cmd.exe /c start "" ${command}`, { background: true })
} }
const openInExplorer = async (path) => { const openInExplorer = async (path) => {
debug.log('Opening path in explorer: ' + path)
createCmdWindow(`explorer.exe "${path}"`) createCmdWindow(`explorer.exe "${path}"`)
} }
@ -17,6 +19,8 @@ async function enableButtons() {
const offBtn = document.querySelector('#playOfficial') const offBtn = document.querySelector('#playOfficial')
const privBtn = document.querySelector('#playPrivate') const privBtn = document.querySelector('#playPrivate')
debug.log('Enabling buttons')
offBtn.classList.remove('disabled') offBtn.classList.remove('disabled')
offBtn.disabled = false offBtn.disabled = false
@ -33,6 +37,8 @@ async function enableButtons() {
async function enableServerButton() { async function enableServerButton() {
const serverBtn = document.querySelector('#serverLaunch') const serverBtn = document.querySelector('#serverLaunch')
debug.log('Enabling server button')
serverBtn.classList.remove('disabled') serverBtn.classList.remove('disabled')
serverBtn.disabled = false serverBtn.disabled = false
} }
@ -44,6 +50,8 @@ async function handleGameNotSet() {
// Set buttons to greyed out and disable // Set buttons to greyed out and disable
document.querySelector('#gamePath').innerHTML = localeObj.folderNotSet || 'Not set' document.querySelector('#gamePath').innerHTML = localeObj.folderNotSet || 'Not set'
debug.log('Handling game not set')
// Set official server background to default // Set official server background to default
document.querySelector('#firstPanel').style.backgroundImage = 'url("../bg/private/default.png")' document.querySelector('#firstPanel').style.backgroundImage = 'url("../bg/private/default.png")'
@ -63,6 +71,8 @@ async function handleServerNotSet() {
// Set buttons to greyed out and disable // Set buttons to greyed out and disable
document.querySelector('#serverPath').innerHTML = localeObj.folderNotSet || 'Not set' document.querySelector('#serverPath').innerHTML = localeObj.folderNotSet || 'Not set'
debug.log('Handling server not set')
// Set official server background to default // Set official server background to default
// document.querySelector('#firstPanel').style.backgroundImage = `url("../bg/private/default.png")` // document.querySelector('#firstPanel').style.backgroundImage = `url("../bg/private/default.png")`
@ -79,6 +89,8 @@ async function displayGameFolder() {
const elm = document.querySelector('#gamePath') const elm = document.querySelector('#gamePath')
const config = await getCfg() const config = await getCfg()
debug.log('Displaying game exe')
elm.innerHTML = config.gameexe elm.innerHTML = config.gameexe
} }
@ -89,6 +101,8 @@ async function displayServerFolder() {
const elm = document.querySelector('#serverPath') const elm = document.querySelector('#serverPath')
const config = await getCfg() const config = await getCfg()
debug.log('Displaying server folder')
elm.innerHTML = config.serverFolder elm.innerHTML = config.serverFolder
} }
@ -107,9 +121,13 @@ async function setBackgroundImage() {
// Set default image, it will change if the bg folder exists // Set default image, it will change if the bg folder exists
document.querySelector('#firstPanel').style.backgroundImage = 'url("https://webstatic.hoyoverse.com/upload/event/2020/11/04/7fd661b5184e1734f91f628b6f89a31f_7367318474207189623.png")' document.querySelector('#firstPanel').style.backgroundImage = 'url("https://webstatic.hoyoverse.com/upload/event/2020/11/04/7fd661b5184e1734f91f628b6f89a31f_7367318474207189623.png")'
debug.log('Setting second panel to: ' + privImage)
// Set the private background image // Set the private background image
document.querySelector('#secondPanel').style.backgroundImage = `url("../bg/private/${privImage}")` document.querySelector('#secondPanel').style.backgroundImage = `url("../bg/private/${privImage}")`
debug.log('Setting third panel to: ' + servImage)
// Set the server background image // Set the server background image
document.querySelector('#thirdPanel').style.backgroundImage = `url("../bg/server/${servImage}")` document.querySelector('#thirdPanel').style.backgroundImage = `url("../bg/server/${servImage}")`
@ -176,6 +194,8 @@ async function handleFavoriteInput() {
const addr = `${ip}:${port}` const addr = `${ip}:${port}`
debug.log('Checking if IP is a favorite: ' + addr)
if (!ip || !ipArr.includes(addr)) { if (!ip || !ipArr.includes(addr)) {
document.querySelector('#star').src = 'icons/star_empty.svg' document.querySelector('#star').src = 'icons/star_empty.svg'
} else { } else {
@ -195,6 +215,8 @@ async function setIp(ip) {
const parseIp = ip.split(':')[0] const parseIp = ip.split(':')[0]
const parsePort = ip.split(':')[1] const parsePort = ip.split(':')[1]
debug.log('Setting IP input elm to: ' + parseIp + ' and port to: ' + parsePort)
// Set star // Set star
if (ip) { if (ip) {
document.querySelector('#star').src = 'icons/star_filled.svg' document.querySelector('#star').src = 'icons/star_filled.svg'
@ -212,6 +234,8 @@ async function handleFavoriteList() {
const ipList = document.querySelector('#ipList') const ipList = document.querySelector('#ipList')
if (ipList.style.display === 'none') { if (ipList.style.display === 'none') {
debug.log('IP list was closed, opening it')
ipList.innerHTML = '' ipList.innerHTML = ''
const list = ipList.appendChild( const list = ipList.appendChild(
@ -219,6 +243,7 @@ async function handleFavoriteList() {
) )
if (ipArr.length < 1) { if (ipArr.length < 1) {
console.log('No favorites found')
const listItem = list.appendChild( const listItem = list.appendChild(
document.createElement('li') document.createElement('li')
) )
@ -239,6 +264,8 @@ async function handleFavoriteList() {
const xy = [ transform.split(',')[4], transform.split(',')[5] ] const xy = [ transform.split(',')[4], transform.split(',')[5] ]
let newY = (27 * ipArr.length) * window.devicePixelRatio let newY = (27 * ipArr.length) * window.devicePixelRatio
debug.log('IP list height: 56vh - ' + newY)
if (ipArr.length === 0 || ipArr.length === 1) newY = 0 if (ipArr.length === 0 || ipArr.length === 1) newY = 0
ipList.style.transform = `translate(${xy[0]}px, calc(56vh - ${newY}px)` ipList.style.transform = `translate(${xy[0]}px, calc(56vh - ${newY}px)`
@ -249,15 +276,19 @@ async function openDownloads() {
const downloads = document.querySelector('#downloadPanel') const downloads = document.querySelector('#downloadPanel')
const config = await getCfg() const config = await getCfg()
debug.log('Opening downloads panel')
if (downloads.style.display === 'none') { if (downloads.style.display === 'none') {
downloads.style.removeProperty('display') downloads.style.removeProperty('display')
} }
// Disable the resource download button if a serverFolder path is not set // Disable the resource download button if a serverFolder path is not set
if (!config.serverFolder) { if (!config.serverFolder) {
debug.log('Server folder not set, disabling resource download button')
document.querySelector('#resourceInstall').disabled = true document.querySelector('#resourceInstall').disabled = true
document.querySelector('#resourceInstall').classList.add('disabled') document.querySelector('#resourceInstall').classList.add('disabled')
} else { } else {
debug.log('Server folder is set, enabling resource download button')
document.querySelector('#resourceInstall').disabled = false document.querySelector('#resourceInstall').disabled = false
document.querySelector('#resourceInstall').classList.remove('disabled') document.querySelector('#resourceInstall').classList.remove('disabled')
} }
@ -266,6 +297,8 @@ async function openDownloads() {
async function closeDownloads() { async function closeDownloads() {
const downloads = document.querySelector('#downloadPanel') const downloads = document.querySelector('#downloadPanel')
debug.log('Closing downloads panel')
downloads.style.display = 'none' downloads.style.display = 'none'
} }
@ -273,6 +306,8 @@ async function openSettings() {
const settings = document.querySelector('#settingsPanel') const settings = document.querySelector('#settingsPanel')
const config = await getCfg() const config = await getCfg()
debug.log('Opening settings panel')
if (settings.style.display === 'none') { if (settings.style.display === 'none') {
settings.style.removeProperty('display') settings.style.removeProperty('display')
} }
@ -286,6 +321,10 @@ async function openSettings() {
serverLaunch.checked = config.serverLaunchPanel serverLaunch.checked = config.serverLaunchPanel
httpsCheckbox.checked = config.useHttps httpsCheckbox.checked = config.useHttps
debug.log('Set killswitch to: ' + config.enableKillswitch)
debug.log('Set server launch to: ' + config.serverLaunchPanel)
debug.log('Set https to: ' + config.useHttps)
// Load languages // Load languages
getLanguages() getLanguages()
@ -297,10 +336,14 @@ async function closeSettings() {
const settings = document.querySelector('#settingsPanel') const settings = document.querySelector('#settingsPanel')
const config = await getCfg() const config = await getCfg()
debug.log('Closing settings panel')
settings.style.display = 'none' settings.style.display = 'none'
// In case we installed the proxy server // In case we installed the proxy server
if (await proxyIsInstalled() && config.gameexe) { if (await proxyIsInstalled() && config.gameexe) {
debug.log('Proxy has been installed and EXE is set, enabling playPrivate')
const playPriv = document.querySelector('#playPrivate') const playPriv = document.querySelector('#playPrivate')
playPriv.classList.remove('disabled') playPriv.classList.remove('disabled')
@ -319,19 +362,28 @@ async function openLogin() {
const useHttps = config.useHttps const useHttps = config.useHttps
const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}` const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}`
debug.log('Opening login panel')
debug.log('Url: ' + url)
// Check if we even need to authenticate // Check if we even need to authenticate
try { try {
const { data } = await axios.get(url + '/authentication/type') const { data } = await axios.get(url + '/authentication/type')
debug.log('Request successful')
if (!data.includes('GCAuthAuthenticationHandler')) { if (!data.includes('GCAuthAuthenticationHandler')) {
debug.log('No authentication required')
launchPrivate() launchPrivate()
return return
} }
} catch(e) { } catch(e) {
debug.warn('Request failed')
launchPrivate() launchPrivate()
return return
} }
debug.log('Login panel opening')
loginIpDisplay.innerText = ip loginIpDisplay.innerText = ip
registerIpDisplay.innerText = ip registerIpDisplay.innerText = ip
@ -343,6 +395,8 @@ async function openLogin() {
async function closeLogin() { async function closeLogin() {
const login = document.querySelector('#loginPanel') const login = document.querySelector('#loginPanel')
debug.log('Closing login panel')
login.style.display = 'none' login.style.display = 'none'
setLoginSection() setLoginSection()
@ -350,16 +404,22 @@ async function closeLogin() {
async function closeFirstTimePopup() { async function closeFirstTimePopup() {
const firstTimePopup = document.querySelector('#firstTimeNotice') const firstTimePopup = document.querySelector('#firstTimeNotice')
debug.log('Closing first time popup')
firstTimePopup.style.display = 'none' firstTimePopup.style.display = 'none'
} }
async function runInstallScript() { async function runInstallScript() {
debug.log('Running install script')
createCmdWindow(`.\\scripts\\install.cmd "${NL_CWD}" true`) createCmdWindow(`.\\scripts\\install.cmd "${NL_CWD}" true`)
// Create an interval that will check for the proxy server installation finish // Create an interval that will check for the proxy server installation finish
const interval = setInterval(async () => { const interval = setInterval(async () => {
debug.log('Checking if proxy server is installed')
if (await proxyIsInstalled()) { if (await proxyIsInstalled()) {
clearInterval(interval) clearInterval(interval)
debug.log('Proxy server installed')
enableButtons() enableButtons()
} }
}, 1000) }, 1000)
@ -379,9 +439,11 @@ async function checkForUpdatesAndShow() {
// Version mismatch? Update! // Version mismatch? Update!
if (manifest?.version !== NL_APPVERSION) { if (manifest?.version !== NL_APPVERSION) {
debug.log('New update available')
subtitle.innerHTML = 'New update available!' subtitle.innerHTML = 'New update available!'
updateBtn.classList.remove('disabled') updateBtn.classList.remove('disabled')
} else { } else {
debug.log('New update not available')
subtitle.innerHTML = 'You are on the latest version! :)' subtitle.innerHTML = 'You are on the latest version! :)'
updateBtn.classList.add('disabled') updateBtn.classList.add('disabled')
} }
@ -391,10 +453,14 @@ async function displayServerLaunchSection() {
const serverPanel = document.querySelector('#thirdPanel') const serverPanel = document.querySelector('#thirdPanel')
const bottomBtnSection = document.querySelector('#serverPath').parentElement const bottomBtnSection = document.querySelector('#serverPath').parentElement
debug.log('Displaying server launch section')
if (serverPanel.style.display === 'none') { if (serverPanel.style.display === 'none') {
debug.log('Showing server launch section')
serverPanel.style.removeProperty('display') serverPanel.style.removeProperty('display')
bottomBtnSection.style.removeProperty('display') bottomBtnSection.style.removeProperty('display')
} else { } else {
debug.log('Hiding server launch section')
serverPanel.style.display = 'none' serverPanel.style.display = 'none'
bottomBtnSection.style.display = 'none' bottomBtnSection.style.display = 'none'
} }
@ -410,8 +476,10 @@ async function setGameExe() {
] ]
}) })
debug.log('Game exe selected: ' + gameExe[0])
if (!gameExe[0]) return if (!gameExe[0]) return
if (hasForeignChars(gameExe[0])) displayAlert(localeObj.foreignCharacterAlert || 'The file path set contains Chinese characters, this may cause problems!') if (hasForeignChars(gameExe[0])) displayAlert(localeObj.foreignCharacterAlert || 'The file path set contains foreign characters, this may cause problems!')
// Set the folder in our configuration // Set the folder in our configuration
const config = await getCfg() const config = await getCfg()
@ -419,6 +487,8 @@ async function setGameExe() {
// It's an array of selections, so only get the first one // It's an array of selections, so only get the first one
config.gameexe = gameExe[0].replace(/\//g, '\\') config.gameexe = gameExe[0].replace(/\//g, '\\')
debug.log('Setting game exe to: ' + config.gameexe)
Neutralino.storage.setData('config', JSON.stringify(config)) Neutralino.storage.setData('config', JSON.stringify(config))
// Refresh background and path // Refresh background and path
@ -434,15 +504,18 @@ async function setGrasscutterFolder() {
] ]
}) })
if (!folder[0]) return debug.log('Grasscutter folder selected: ' + folder[0])
console.log(hasForeignChars(folder[0])) if (!folder[0]) return
if (hasForeignChars(folder[0])) displayAlert(localeObj.foreignCharacterAlert || 'The file path set contains foreign characters, this may cause problems!') if (hasForeignChars(folder[0])) displayAlert(localeObj.foreignCharacterAlert || 'The file path set contains foreign characters, this may cause problems!')
// Set the folder in our configuration // Set the folder in our configuration
const config = await getCfg() const config = await getCfg()
config.serverFolder = folder[0] config.serverFolder = folder[0]
debug.log('Setting grasscutter folder to: ' + config.serverFolder)
Neutralino.storage.setData('config', JSON.stringify(config)) Neutralino.storage.setData('config', JSON.stringify(config))
displayServerFolder() displayServerFolder()
@ -455,6 +528,8 @@ async function setGrasscutterFolder() {
async function launchOfficial() { async function launchOfficial() {
const config = await getCfg() const config = await getCfg()
debug.log('Launching game')
Neutralino.os.execCommand(`"${config.gameexe}"`) Neutralino.os.execCommand(`"${config.gameexe}"`)
} }
@ -467,7 +542,7 @@ async function launchPrivate() {
const config = await getCfg() const config = await getCfg()
console.log('connecting to ' + ip + ':' + port) debug.log('Connecting to ' + ip + ':' + port)
// Set the last connect // Set the last connect
config.lastConnect = ip config.lastConnect = ip
@ -478,11 +553,13 @@ async function launchPrivate() {
`.\\scripts\\private_server_launch.cmd ${ip} ${port} ${config.useHttps} "${config.gameexe}" "${NL_CWD}" ${config.enableKillswitch} true`, { `.\\scripts\\private_server_launch.cmd ${ip} ${port} ${config.useHttps} "${config.gameexe}" "${NL_CWD}" ${config.enableKillswitch} true`, {
background: true background: true
} }
).catch(e => console.log(e)) ).catch(e => debug.error(e))
} }
async function launchLocalServer() { async function launchLocalServer() {
const config = await getCfg() const config = await getCfg()
debug.log('Launching local server')
createCmdWindow(`.\\scripts\\local_server_launch.cmd "${config.serverFolder}"`).catch(e => console.log(e)) createCmdWindow(`.\\scripts\\local_server_launch.cmd "${config.serverFolder}"`).catch(e => console.log(e))
} }

View File

@ -7,6 +7,8 @@ async function setLoginSection() {
const loginSection = document.getElementById('loginPopupContentBody') const loginSection = document.getElementById('loginPopupContentBody')
const registerSection = document.getElementById('registerPopupContentBody') const registerSection = document.getElementById('registerPopupContentBody')
debug.log('Setting to login section')
title.classList.add('selectedTitle') title.classList.add('selectedTitle')
altTitle.classList.remove('selectedTitle') altTitle.classList.remove('selectedTitle')
@ -23,6 +25,8 @@ async function setRegisterSection(fromLogin = false) {
const loginSection = document.getElementById('loginPopupContentBody') const loginSection = document.getElementById('loginPopupContentBody')
const registerSection = document.getElementById('registerPopupContentBody') const registerSection = document.getElementById('registerPopupContentBody')
debug.log('Setting to register section')
title.classList.add('selectedTitle') title.classList.add('selectedTitle')
altTitle.classList.remove('selectedTitle') altTitle.classList.remove('selectedTitle')
@ -30,6 +34,8 @@ async function setRegisterSection(fromLogin = false) {
registerSection.style.removeProperty('display') registerSection.style.removeProperty('display')
if (fromLogin) { if (fromLogin) {
debug.log('Just registered, setting to login page')
// Take the values from the login section and put them in the register section // Take the values from the login section and put them in the register section
const loginUsername = document.getElementById('loginUsername').value const loginUsername = document.getElementById('loginUsername').value
const loginPassword = document.getElementById('loginPassword').value const loginPassword = document.getElementById('loginPassword').value
@ -42,6 +48,9 @@ async function setRegisterSection(fromLogin = false) {
function parseJwt(token) { function parseJwt(token) {
const base64Url = token.split('.')[1] const base64Url = token.split('.')[1]
const base64 = base64Url.replace('-', '+').replace('_', '/') const base64 = base64Url.replace('-', '+').replace('_', '/')
debug.log('Parsed JWT: ' + base64)
return JSON.parse(window.atob(base64)) return JSON.parse(window.atob(base64))
} }
@ -57,12 +66,14 @@ async function login() {
const useHttps = config.useHttps const useHttps = config.useHttps
const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}` const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}`
debug.log('Attempting login to ' + url)
const reqBody = { const reqBody = {
username, username,
password, password,
} }
const { data } = await axios.post(url + '/authentication/login', reqBody) const { data } = await axios.post(url + '/authentication/login', reqBody).catch(e => debug.error('Login request failed: ' + e))
switch(data.message) { switch(data.message) {
case 'INVALID_ACCOUNT': case 'INVALID_ACCOUNT':
@ -92,6 +103,8 @@ async function login() {
const tkData = parseJwt(data.jwt) const tkData = parseJwt(data.jwt)
await Neutralino.clipboard.writeText(tkData.token) await Neutralino.clipboard.writeText(tkData.token)
debug.log('Login success')
displayLoginAlert(localeObj.alertLoginSuccess || 'Login successful! Token copied to clipboard. Paste this token into the username field of the game to log in.', 'success', 8000) displayLoginAlert(localeObj.alertLoginSuccess || 'Login successful! Token copied to clipboard. Paste this token into the username field of the game to log in.', 'success', 8000)
launchPrivate() launchPrivate()
break break
@ -111,13 +124,15 @@ async function register() {
const useHttps = config.useHttps const useHttps = config.useHttps
const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}` const url = `${useHttps ? 'https' : 'http'}://${ip}:${port}`
debug.log('Attempting registration to ' + url)
const reqBody = { const reqBody = {
username, username,
password, password,
password_confirmation password_confirmation
} }
const { data } = await axios.post(url + '/authentication/register', reqBody) const { data } = await axios.post(url + '/authentication/register', reqBody).catch(e => debug.error('Registration request failed: ' + e))
switch(data.message) { switch(data.message) {
case 'USERNAME_TAKEN': case 'USERNAME_TAKEN':
@ -147,6 +162,8 @@ async function register() {
const loginUsername = document.getElementById('loginUsername') const loginUsername = document.getElementById('loginUsername')
loginUsername.value = username loginUsername.value = username
debug.log('Registered with username ' + username)
setLoginSection() setLoginSection()
displayLoginAlert(localeObj.alertRegisterSuccess || 'Registration successful!', 'success', 5000) displayLoginAlert(localeObj.alertRegisterSuccess || 'Registration successful!', 'success', 5000)
break break

View File

@ -7,6 +7,8 @@ async function toggleKillSwitch() {
config.enableKillswitch = killSwitch.checked config.enableKillswitch = killSwitch.checked
debug.log('Killswitch is now ', config.enableKillswitch)
Neutralino.storage.setData('config', JSON.stringify(config)) Neutralino.storage.setData('config', JSON.stringify(config))
} }
@ -18,6 +20,8 @@ async function toggleServerLaunchSection() {
displayServerLaunchSection() displayServerLaunchSection()
debug.log('Toggling server panel')
// Save setting // Save setting
config.serverLaunchPanel = !config.serverLaunchPanel config.serverLaunchPanel = !config.serverLaunchPanel
Neutralino.storage.setData('config', JSON.stringify(config)) Neutralino.storage.setData('config', JSON.stringify(config))
@ -26,6 +30,8 @@ async function toggleServerLaunchSection() {
if (config.serverLaunchPanel && !config.serverFolder) { if (config.serverLaunchPanel && !config.serverFolder) {
closeSettings() closeSettings()
debug.log('First time server launcher')
openDialog( openDialog(
localeObj.serverEnableDialogTitle || 'You found the Grasscutter server launcher!', localeObj.serverEnableDialogTitle || 'You found the Grasscutter server launcher!',
localeObj.serverEnableDialogText || 'If you do not have an existing Grasscutter installation to set, would you like to download a build?', localeObj.serverEnableDialogText || 'If you do not have an existing Grasscutter installation to set, would you like to download a build?',
@ -42,6 +48,8 @@ async function getLanguages() {
const languageFiles = (await filesystem.readDirectory(`${NL_CWD}/languages`)).filter(file => file.entry.endsWith('.json')) const languageFiles = (await filesystem.readDirectory(`${NL_CWD}/languages`)).filter(file => file.entry.endsWith('.json'))
const config = await getCfg() const config = await getCfg()
debug.log('Grabbing languages')
// Clear language options // Clear language options
const languageSelect = document.querySelector('#languageSelect') const languageSelect = document.querySelector('#languageSelect')
languageSelect.innerHTML = '' languageSelect.innerHTML = ''
@ -51,12 +59,15 @@ async function getLanguages() {
const fullLanguageName = JSON.parse(await filesystem.readFile(`${NL_CWD}/languages/${file.entry}`)).fullLangName const fullLanguageName = JSON.parse(await filesystem.readFile(`${NL_CWD}/languages/${file.entry}`)).fullLangName
const lang = file.entry.split('.json')[0] const lang = file.entry.split('.json')[0]
debug.log('Loading language: ', lang)
const option = document.createElement('option') const option = document.createElement('option')
option.value = lang option.value = lang
option.innerHTML = fullLanguageName option.innerHTML = fullLanguageName
// Set language selected to config language // Set language selected to config language
if (lang === config.language) { if (lang === config.language) {
debug.log('Selected language: ', lang)
option.selected = true option.selected = true
} }
@ -77,6 +88,8 @@ async function handleLanguageChange(elm) {
config.language = list.value config.language = list.value
Neutralino.storage.setData('config', JSON.stringify(config)) Neutralino.storage.setData('config', JSON.stringify(config))
debug.log('Language changed to: ', list.value)
// Force refresh of application, no need for restart! // Force refresh of application, no need for restart!
window.location.reload() window.location.reload()
} }
@ -90,6 +103,22 @@ async function toggleHttps() {
config.useHttps = httpsCheckbox.checked config.useHttps = httpsCheckbox.checked
debug.log('HTTPS set to: ', config.useHttps)
Neutralino.storage.setData('config', JSON.stringify(config))
}
/**
* Toggle debugging
*/
async function toggleDebugging() {
const debugCheckbox = document.querySelector('#debugOption')
const config = await getCfg()
config.debug = debugCheckbox.checked
debug.log('Debugging set to: ', config.debug)
Neutralino.storage.setData('config', JSON.stringify(config)) Neutralino.storage.setData('config', JSON.stringify(config))
} }
@ -105,12 +134,16 @@ async function setFavorite() {
const addr = `${ip}:${port}` const addr = `${ip}:${port}`
debug.log('Handling favorite: ', addr)
// Set star icon // Set star icon
const star = document.querySelector('#star') const star = document.querySelector('#star')
if (star.src.includes('filled') && ip) { if (star.src.includes('filled') && ip) {
star.src = 'icons/star_empty.svg' star.src = 'icons/star_empty.svg'
debug.log('Removing from list: ', addr)
// remove from list // remove from list
ipArr.splice(ipArr.indexOf(addr), 1) ipArr.splice(ipArr.indexOf(addr), 1)
} else { } else {
@ -118,6 +151,7 @@ async function setFavorite() {
// add to list // add to list
if (ip && !ipArr.includes(addr)) { if (ip && !ipArr.includes(addr)) {
debug.log('Adding to list: ', addr)
ipArr.push(addr) ipArr.push(addr)
} }
} }