# Code for the login screen and the account creation screen. from helpers import defaultAppSettings, message_dialog, quitKB, errorTxt, isValidUsername from prompt_toolkit import Application from prompt_toolkit.buffer import Buffer from prompt_toolkit.validation import Validator from prompt_toolkit.widgets import Button, Dialog, Label, ValidationToolbar, RadioList, TextArea from prompt_toolkit.layout.containers import HSplit from prompt_toolkit.application.current import get_app from prompt_toolkit.layout.layout import Layout from prompt_toolkit.layout.dimension import Dimension as D async def firstSetupScreen(intset,server): def ok_handler() -> None: get_app().exit() ok_button = Button(text="OK", handler=ok_handler, width=16) colorselect = RadioList([(24,"24 bits (True Color)"),(8,"8 bits (Paletted)"),(4,"4 bits (ANSI/RGBI)"),(1,"1 bit (Monochrome)")],default=8) encselect = RadioList([("utf8","UTF-8 (Unicode)"),("ascii","ASCII (7-bit)"),("latin_1","ISO-8859-1 (Ext. ASCII)"),("cp437","CP437 (Extended ASCII)")],default="utf8") cdialog = Dialog( title="First Setup", body=HSplit( [ Label(text="Please select a color depth supported by this terminal:", dont_extend_height=True), colorselect, Label(text="Use 1 or 4 bits for compatibility with older terminals, otherwise 8 or 24 bits.", dont_extend_height=True), Label(text="You can always change this later in the interface settings.",dont_extend_height=True), ValidationToolbar(), ], padding=D(preferred=1, max=1), ), buttons=[ok_button], with_background=True, ) capp = Application(layout=Layout(cdialog), **defaultAppSettings(intset)) await capp.run_async() edialog = Dialog( title="First Setup", body=HSplit( [ Label(text="Please insert the text encoding supported by this terminal:", dont_extend_height=True), encselect, Label(text="Use ASCII for compatibility with older terminals, otherwise UTF-8.", dont_extend_height=True), Label(text="You can always change this later in the interface settings.",dont_extend_height=True), ValidationToolbar(), ], padding=D(preferred=1, max=1), ), buttons=[ok_button], with_background=True, ) eapp = Application(layout=Layout(edialog), **defaultAppSettings(intset)) await eapp.run_async() return {"color":colorselect.current_value,"encoding":encselect.current_value} async def createAccountScreen(intset,server): def nameaccept(buf: Buffer) -> bool: get_app().layout.focus(passtextfield) return True # Keep text. def pwrdaccept(buf: Buffer) -> bool: # get_app().layout.focus(login_button) get_app().layout.focus(passtextconffield) return True # Keep text. def pwrdcaccept(buf: Buffer) -> bool: # get_app().layout.focus(login_button) ok_handler() return True # Keep text. def _return_none() -> None: "Button handler that returns None." get_app().exit() def ok_handler() -> None: get_app().exit(result=(usertextfield.text,passtextfield.text)) def login_handler() -> None: get_app().exit(result="login") create_button = Button(text="Create Account", handler=ok_handler, width=16) login_button = Button(text="Log In", handler=login_handler, width=16) exit_button = Button(text="Exit", handler=_return_none, width=16) usernameValidator = Validator.from_callable(isValidUsername, error_message='Invalid username') samePassValidator = Validator.from_callable(lambda x: passtextfield.text==x, error_message='Passwords are not the same') usertextfield = TextArea( text="", multiline=False, password=False, completer=None, validator=usernameValidator, accept_handler=nameaccept, ) passtextfield = TextArea( text="", multiline=False, password=True, completer=None, validator=None, accept_handler=pwrdaccept, ) passtextconffield = TextArea( text="", multiline=False, password=True, completer=None, validator=samePassValidator, accept_handler=pwrdcaccept, ) dialog = Dialog( title="Create a StingNET account", body=HSplit( [ Label(text="Username:", dont_extend_height=True), usertextfield, Label(text="Password:", dont_extend_height=True), passtextfield, Label(text="Password (confirm):", dont_extend_height=True), passtextconffield, ValidationToolbar(), ], padding=D(preferred=1, max=1), ), buttons=[create_button, login_button, exit_button], with_background=True, ) app = Application(key_bindings=quitKB, layout=Layout(dialog), **defaultAppSettings(intset)) while True: usertextfield.text = "" passtextfield.text = "" passtextconffield.text = "" appres = await app.run_async() if type(appres)==tuple: name,pwrd = appres elif type(appres)==str and appres=="login": return "login" else: await server.disconnect() exit() res = await server.createuser(name,pwrd) if res["type"]=="response": lres = await server.login(name,pwrd) else: await message_dialog(intset,title="Error (create)",text=f"The account has not been created.\n{errorTxt(res)}").run_async() continue if lres["type"]=="error": await message_dialog(intset,title="Error (login)",text=f"The account has been created, but has not been logged in.\n{errorTxt(lres)}").run_async() continue else: break async def loginCredsScreen(intset,server): def nameaccept(buf: Buffer) -> bool: get_app().layout.focus(passtextfield) return True # Keep text. def pwrdaccept(buf: Buffer) -> bool: # get_app().layout.focus(login_button) ok_handler() return True # Keep text. def _return_none() -> None: "Button handler that returns None." get_app().exit() def ok_handler() -> None: get_app().exit(result=(usertextfield.text,passtextfield.text)) def create_handler() -> None: get_app().exit(result="create") def guest_handler() -> None: get_app().exit(result="guest") login_button = Button(text="Log In", handler=ok_handler, width=16) create_button = Button(text="Create Account", handler=create_handler, width=16) guest_button = Button(text="Use Guest", handler=guest_handler, width=16) exit_button = Button(text="Exit", handler=_return_none, width=16) usernameValidator = Validator.from_callable(isValidUsername, error_message='Invalid username') usertextfield = TextArea( text="", multiline=False, password=False, completer=None, validator=usernameValidator, accept_handler=nameaccept, ) passtextfield = TextArea( text="", multiline=False, password=True, completer=None, validator=None, accept_handler=pwrdaccept, ) dialog = Dialog( title="Log in to StingNET", body=HSplit( [ Label(text="Username:", dont_extend_height=True), usertextfield, Label(text="Password:", dont_extend_height=True), passtextfield, ValidationToolbar(), ], padding=D(preferred=1, max=1), ), buttons=[login_button, create_button, guest_button, exit_button], with_background=True, ) app = Application(key_bindings=quitKB, layout=Layout(dialog), **defaultAppSettings(intset)) while True: usertextfield.text = "" passtextfield.text = "" appres = await app.run_async() if type(appres)==tuple: name,pwrd = appres elif type(appres)==str: return appres else: await server.disconnect() exit() res = await server.login(name,pwrd) if res["type"]=="error": await message_dialog(intset,title="Error",text=errorTxt(res)).run_async() else: break async def loginScreen(intset,server): while True: res = await loginCredsScreen(intset,server) if res != "create": return res res = await createAccountScreen(intset,server) if res != "login": return res