From 41c113be9abd796dc06926fbd7981b5f28eeaed0 Mon Sep 17 00:00:00 2001
From: Simon Ser <contact@emersion.fr>
Date: Sun, 6 Jun 2021 11:33:00 +0200
Subject: [PATCH] Show connect form during connection

This improves UX when the connection parameters (server URL,
username, password, and so on) are incorrect.
---
 components/app.js          | 11 +++++++++--
 components/connect-form.js | 38 +++++++++++++++++++++++++-------------
 2 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/components/app.js b/components/app.js
index bdee786..f0e63c1 100644
--- a/components/app.js
+++ b/components/app.js
@@ -104,6 +104,7 @@ export default class App extends Component {
 		buffers: new Map(),
 		bouncerNetworks: new Map(),
 		activeBuffer: null,
+		connectForm: true,
 		dialog: null,
 		error: null,
 		openPanels: {
@@ -203,6 +204,7 @@ export default class App extends Component {
 		});
 
 		if (connectParams.autoconnect) {
+			this.setState({ connectForm: false });
 			this.connect(connectParams);
 		}
 	}
@@ -430,6 +432,9 @@ export default class App extends Component {
 
 		client.addEventListener("status", () => {
 			this.setServerState(serverID, { status: client.status });
+			if (client.status === Client.Status.REGISTERED) {
+				this.setState({ connectForm: false });
+			}
 		});
 
 		client.addEventListener("message", (event) => {
@@ -1173,14 +1178,16 @@ export default class App extends Component {
 			}
 		}
 
-		if (!activeServer || (activeServer.status !== ServerStatus.REGISTERED && !activeBuffer)) {
+		if (this.state.connectForm) {
+			var status = activeServer ? activeServer.status : ServerStatus.DISCONNECTED;
+			var connecting = status === ServerStatus.CONNECTING || status === ServerStatus.REGISTERING;
 			// TODO: using key=connectParams trashes the ConnectForm state on update
 			return html`
 				<section id="connect">
 					<${ConnectForm}
 						error=${this.state.error}
 						params=${this.state.connectParams}
-						disabled=${activeServer}
+						connecting=${connecting}
 						onSubmit=${this.handleConnectSubmit}
 						key=${this.state.connectParams}
 					/>
diff --git a/components/connect-form.js b/components/connect-form.js
index 8fe3539..ae80c64 100644
--- a/components/connect-form.js
+++ b/components/connect-form.js
@@ -40,7 +40,7 @@ export default class ConnectForm extends Component {
 	handleSubmit(event) {
 		event.preventDefault();
 
-		if (this.props.disabled) {
+		if (this.props.connecting) {
 			return;
 		}
 
@@ -74,35 +74,48 @@ export default class ConnectForm extends Component {
 	}
 
 	render() {
+		var disabled = this.props.connecting;
+
 		var serverURL = null;
 		if (!this.props.params || !this.props.params.url) {
 			serverURL = html`
 				<label>
 					Server URL:<br/>
-					<input type="text" name="url" value=${this.state.url} disabled=${this.props.disabled} inputmode="url"/>
+					<input type="text" name="url" value=${this.state.url} disabled=${disabled} inputmode="url"/>
 				</label>
 				<br/><br/>
 			`;
 		}
 
+		var status = null;
+		if (this.props.connecting) {
+			status = html`
+				<p>Connecting...</p>
+			`;
+		} else if (this.props.error) {
+			status = html`
+				<p class="error-text">${this.props.error}</p>
+			`;
+		}
+
 		return html`
 			<form onChange=${this.handleChange} onSubmit=${this.handleSubmit}>
 				<h2>Connect to IRC</h2>
 
 				<label>
 					Nickname:<br/>
-					<input type="username" name="nick" value=${this.state.nick} disabled=${this.props.disabled} autofocus required/>
+					<input type="username" name="nick" value=${this.state.nick} disabled=${disabled} autofocus required/>
 				</label>
 				<br/><br/>
 
 				<label>
 					Password:<br/>
-					<input type="password" name="password" value=${this.state.password} disabled=${this.props.disabled}/>
+					<input type="password" name="password" value=${this.state.password} disabled=${disabled}/>
 				</label>
 				<br/><br/>
 
 				<label>
-					<input type="checkbox" name="rememberMe" checked=${this.state.rememberMe} disabled=${this.props.disabled}/>
+					<input type="checkbox" name="rememberMe" checked=${this.state.rememberMe} disabled=${disabled}/>
 					Remember me
 				</label>
 				<br/><br/>
@@ -116,34 +129,33 @@ export default class ConnectForm extends Component {
 
 					<label>
 						Username:<br/>
-						<input type="username" name="username" value=${this.state.username} disabled=${this.props.disabled} placeholder="Same as nickname"/>
+						<input type="username" name="username" value=${this.state.username} disabled=${disabled} placeholder="Same as nickname"/>
 					</label>
 					<br/><br/>
 
 					<label>
 						Real name:<br/>
-						<input type="text" name="realname" value=${this.state.realname} disabled=${this.props.disabled} placeholder="Same as nickname"/>
+						<input type="text" name="realname" value=${this.state.realname} disabled=${disabled} placeholder="Same as nickname"/>
 					</label>
 					<br/><br/>
 
 					<label>
 						Server password:<br/>
-						<input type="text" name="pass" value=${this.state.pass} disabled=${this.props.disabled} placeholder="None"/>
+						<input type="text" name="pass" value=${this.state.pass} disabled=${disabled} placeholder="None"/>
 					</label>
 					<br/><br/>
 
 					<label>
 						Auto-join channels:<br/>
-						<input type="text" name="autojoin" value=${this.state.autojoin} disabled=${this.props.disabled} placeholder="Comma-separated list of channels"/>
+						<input type="text" name="autojoin" value=${this.state.autojoin} disabled=${disabled} placeholder="Comma-separated list of channels"/>
 					</label>
 					<br/>
 				</details>
 
 				<br/>
-				${this.props.error ? html`
-					<p class="error-text">${this.props.error || ""}</p>
-				` : null}
-				<button disabled=${this.props.disabled}>Connect</button>
+				<button disabled=${disabled}>Connect</button>
+
+				${status}
 			</form>
 		`;
 	}