procrealms-client
Version:
A web/terminal hybrid client for Procedural Realms
316 lines (263 loc) • 8.13 kB
JavaScript
const Blessed = require('@dinchak/blessed')
const Conn = require('../conn')
const Graphic = require('./graphic')
const Log = require('../log')
const State = require('../state')
const U = require('../utils')
const UI = require('../ui')
let label
let name
let password
let tutorial
exports.loginForm = {
name: '',
password: ''
}
exports.create = function (screen) {
let component = Blessed.box({
name: 'login',
top: 0,
left: 0,
height: '100%',
width: '100%',
tags: true,
style: {
fg: 'lightwhite',
bg: 'black'
}
})
label = Blessed.box({
name: 'label',
top: 5,
tags: true,
left: '50%-29',
width: 58,
border: {
type: 'line'
},
height: 7,
style: {
fg: 'lightwhite',
bg: 'lightblue'
}
})
name = Blessed.textbox({
name: 'name',
top: 9,
left: '50%-13',
keys: false,
width: 26,
height: 1,
style: {
fg: 'lightyellow',
bg: 'gray'
}
})
password = Blessed.textbox({
name: 'password',
top: 9,
left: '50%-13',
keys: false,
censor: true,
width: 26,
height: 1,
style: {
fg: 'lightyellow',
bg: 'gray'
}
})
tutorial = Blessed.textbox({
name: 'tutorial',
top: 9,
left: '50%-1',
keys: false,
width: 1,
height: 1,
style: {
fg: 'lightyellow',
bg: 'gray'
}
})
password.on('cancel', () => onPasswordCancel(screen))
tutorial.on('cancel', () => onTutorialCancel(screen))
component.append(label)
component.append(name)
component.append(password)
component.append(tutorial)
name.hide()
password.hide()
tutorial.hide()
component.on('prerender', () => prerender(component, screen))
component.on('keypress', (ch, key) => onKey(component, screen, ch, key))
component.hide()
return component
}
function prerender (component, screen) {
component.setContent(`{center}${Graphic.render()}{/center}`)
// if (State.picture) {
// // component.screen.program._write(U.parseAnsi(State.picture))
// // process.exit()
// component.setContent(`{center}${U.parseAnsi(State.picture)}{/center}`)
// }
}
exports.setLoginStep = function (newStep) {
Log.write(`Login.setLoginStep(${newStep})`)
State.loginStep = newStep
if (State.loginStep == 'connecting') {
label.setContent(U.parseAnsi(`\n{center}{{WConnecting to ${Conn.url}{/center}`,))
}
if (State.loginStep == 'connectFailed') {
label.setContent(U.parseAnsi(`\n{center}{{WConnection to server at ${Conn.url} was lost.\nRetry connection attempt #${Conn.attempt} in ${Conn.timeout} seconds...{/center}`,))
deactivateTextArea(name)
}
if (State.loginStep == 'name') {
label.setContent(U.parseAnsi('\n{center}{{WGreetings, adventurer! By what name are you known?{/center}',))
activateTextArea(name)
}
if (State.loginStep == 'tokenFailed') {
label.setContent(U.parseAnsi('\n{center}{{WApologies, your token has expired By what name are you known?!{/center}',))
activateTextArea(name)
}
if (State.loginStep == 'loginFailed') {
label.setContent(U.parseAnsi('\n{center}{{WSorry, I do not recognize that name and password combination. By what name are you known?{/center}',))
activateTextArea(name)
}
if (State.loginStep == 'validationFailed') {
label.setContent(U.parseAnsi('\n{center}{{WSorry, that name is invalid or already taken. Please choose another name.{/center}',))
activateTextArea(name)
}
if (State.loginStep == 'password') {
label.setContent(U.parseAnsi('\n{center}{{WEnter your password{/center}',))
activateTextArea(password, true)
}
if (State.loginStep == 'choosePassword') {
label.setContent(U.parseAnsi(`\n{center}{{WAh, you must be new here, {{Y${exports.loginForm.name}{{W! Welcome!\nPlease choose a password.{/center}`,))
activateTextArea(password, true)
}
if (State.loginStep == 'confirmPassword') {
label.setContent(U.parseAnsi(`\n{center}{{WCould you repeat that password?{/center}`,))
activateTextArea(password, true)
}
if (State.loginStep == 'tutorial') {
label.setContent(U.parseAnsi(`\n{center}{{WWould you like to start the tutorial? [Y/n]{/center}`,))
activateTextArea(tutorial)
}
if (State.loginStep == 'waiting') {
label.setContent(U.parseAnsi('\n{center}{{WPlease wait...{/center}',))
}
}
function onPasswordCancel (screen) {
deactivateTextArea(password)
if (State.loginStep == 'confirmPassword') {
exports.setLoginStep('choosePassword')
return
}
exports.setLoginStep('name')
}
function onTutorialCancel (screen) {
Log.write('onTutorialCancel tutorial.hide()')
deactivateTextArea(tutorial)
exports.setLoginStep('confirmPassword')
}
function onKey (component, screen, ch, key) {
Log.write(`ch=${ch}, key=${JSON.stringify(key)}`)
if (key.name == 'escape' && ['name', 'loginFailed', 'tokenFailed'].includes(State.loginStep)) {
Log.write(`got escape on name loginStep`)
if (!U.inBrowser()) {
return process.exit()
}
}
if (key.name == 'return' && ['name', 'loginFailed', 'tokenFailed'].includes(State.loginStep)) {
exports.loginForm.name = U.ucfirst(name.getValue())
Log.write(`set loginForm name=${exports.loginForm.name}`)
if (exports.loginForm.name.length < 3) {
label.setContent(`\n{center}Name is too short{/center}`)
process.nextTick(() => name.readInput())
return
}
if (exports.loginForm.name.length > 15) {
label.setContent(`\n{center}Name is too long{/center}`)
process.nextTick(() => name.readInput())
return
}
if (!exports.loginForm.name.match(/^[a-zA-Z]+$/)) {
label.setContent(`\n{center}Invalid characters in name{/center}`)
process.nextTick(() => name.readInput())
return
}
deactivateTextArea(name)
exports.setLoginStep('waiting')
Conn.send('nameExists', { name: exports.loginForm.name })
return
}
if (key.name == 'return' && State.loginStep == 'password') {
Log.write(`set loginForm password=...`)
exports.loginForm.password = password.getValue()
exports.loginForm.width = UI.getTerminalWidth()
exports.loginForm.height = UI.getTerminalHeight()
deactivateTextArea(password)
exports.setLoginStep('waiting')
Conn.send('login', exports.loginForm)
return
}
if (key.name == 'return' && State.loginStep == 'choosePassword') {
Log.write(`set loginForm password=...`)
exports.loginForm.password = password.getValue()
deactivateTextArea(password)
exports.setLoginStep('confirmPassword')
return
}
if (key.name == 'return' && State.loginStep == 'confirmPassword') {
deactivateTextArea(password)
if (exports.loginForm.password == password.getValue()) {
exports.setLoginStep('tutorial')
} else {
exports.setLoginStep('choosePassword')
}
screen.render()
return
}
if (key.name == 'return' && State.loginStep == 'tutorial') {
let value = U.ucfirst(tutorial.getValue())
if (!['Y', 'N'].includes(value)) {
process.nextTick(() => tutorial.readInput())
return
}
exports.loginForm.tutorial = value
exports.loginForm.width = UI.getTerminalWidth()
exports.loginForm.height = UI.getTerminalHeight()
deactivateTextArea(tutorial)
exports.setLoginStep('waiting')
screen.render()
Conn.send('create', exports.loginForm)
return
}
}
function activateTextArea (textArea, clearValue) {
if (!textArea.visible) {
Log.write(`${textArea.name}.show()`)
textArea.show()
}
if (!textArea.focused) {
Log.write(`${textArea.name}.focus()`)
textArea.focus()
if (clearValue) {
Log.write(`${textArea.name}.clearValue()`)
textArea.clearValue()
}
}
if (!textArea._reading) {
Log.write(`${textArea.name}.readInput()`)
textArea.readInput()
}
}
function deactivateTextArea (textArea) {
if (textArea.focused) {
Log.write(`${textArea.name}.screen.focusPop()`)
textArea.screen.focusPop()
}
if (textArea.visible) {
Log.write(`${textArea.name}.hide()`)
textArea.hide()
}
}