Add error reporting on connect and main page

This commit is contained in:
bbworld1 2020-08-07 21:08:51 -07:00 committed by Simon Ser
parent 96c890f1f5
commit 16582a6592
No known key found for this signature in database
GPG key ID: 0FDE7BE0E88F5E48
4 changed files with 49 additions and 13 deletions

View file

@ -98,6 +98,7 @@ export default class App extends Component {
status: Status.DISCONNECTED, status: Status.DISCONNECTED,
buffers: new Map(), buffers: new Map(),
activeBuffer: null, activeBuffer: null,
error: null,
}; };
pendingHistory = Promise.resolve(null); pendingHistory = Promise.resolve(null);
endOfHistory = new Map(); endOfHistory = new Map();
@ -115,6 +116,7 @@ export default class App extends Component {
this.handleJoinClick = this.handleJoinClick.bind(this); this.handleJoinClick = this.handleJoinClick.bind(this);
this.autocomplete = this.autocomplete.bind(this); this.autocomplete = this.autocomplete.bind(this);
this.handleBufferScrollTop = this.handleBufferScrollTop.bind(this); this.handleBufferScrollTop = this.handleBufferScrollTop.bind(this);
this.dismissError = this.dismissError.bind(this);
this.saveReceipts = debounce(this.saveReceipts.bind(this), 500); this.saveReceipts = debounce(this.saveReceipts.bind(this), 500);
@ -157,6 +159,11 @@ export default class App extends Component {
} }
} }
dismissError(event) {
event.preventDefault();
this.setState({ error: null });
}
setBufferState(name, updater, callback) { setBufferState(name, updater, callback) {
this.setState((state) => { this.setState((state) => {
var buf = state.buffers.get(name); var buf = state.buffers.get(name);
@ -353,6 +360,12 @@ export default class App extends Component {
this.handleMessage(event.detail.message); this.handleMessage(event.detail.message);
}); });
this.client.addEventListener("error", (event) => {
this.setState({
error: event.detail,
});
});
this.createBuffer(SERVER_BUFFER); this.createBuffer(SERVER_BUFFER);
this.switchBuffer(SERVER_BUFFER); this.switchBuffer(SERVER_BUFFER);
} }
@ -461,7 +474,7 @@ export default class App extends Component {
var after = receipt; var after = receipt;
var before = { time: msg.tags.time || irc.formatDate(new Date()) }; var before = { time: msg.tags.time || irc.formatDate(new Date()) };
this.fetchHistoryBetween(channel, after, before, CHATHISTORY_MAX_SIZE).catch((err) => { this.fetchHistoryBetween(channel, after, before, CHATHISTORY_MAX_SIZE).catch((err) => {
console.error("Failed to fetch history:", err); this.setState({ error: "Failed to fetch history: " + err });
this.receipts.delete(channel); this.receipts.delete(channel);
this.saveReceipts(); this.saveReceipts();
}); });
@ -605,20 +618,20 @@ export default class App extends Component {
var cmd = commands[name]; var cmd = commands[name];
if (!cmd) { if (!cmd) {
console.error("Unknwon command '" + name + "'"); this.setState({ error: "Unknown command '" + name + "'" });
return; return;
} }
try { try {
cmd(this, args); cmd(this, args);
} catch (err) { } catch (error) {
console.error(err); this.setState({ error });
} }
} }
privmsg(target, text) { privmsg(target, text) {
if (target == SERVER_BUFFER) { if (target == SERVER_BUFFER) {
console.error("Cannot send message in server buffer"); this.setState({ error: "Cannot send message in server buffer" });
return; return;
} }
@ -787,7 +800,7 @@ export default class App extends Component {
if (this.state.status != Status.REGISTERED) { if (this.state.status != Status.REGISTERED) {
return html` return html`
<section id="connect"> <section id="connect">
<${Connect} params=${this.state.connectParams} disabled=${this.state.status != Status.DISCONNECTED} onSubmit=${this.handleConnectSubmit}/> <${Connect} error=${this.state.error} params=${this.state.connectParams} disabled=${this.state.status != Status.DISCONNECTED} onSubmit=${this.handleConnectSubmit}/>
</section> </section>
`; `;
} }
@ -833,6 +846,9 @@ export default class App extends Component {
</> </>
${memberList} ${memberList}
<${Composer} ref=${this.composer} readOnly=${this.state.activeBuffer == SERVER_BUFFER} onSubmit=${this.handleComposerSubmit} autocomplete=${this.autocomplete}/> <${Composer} ref=${this.composer} readOnly=${this.state.activeBuffer == SERVER_BUFFER} onSubmit=${this.handleComposerSubmit} autocomplete=${this.autocomplete}/>
${this.state.error ? html`
<p id="error-msg">${this.state.error} <a href="#" onClick=${this.dismissError}>×</a></p>
` : null}
`; `;
} }
} }

View file

@ -140,7 +140,9 @@ export default class Connect extends Component {
</details> </details>
<br/> <br/>
${this.props.error ? html`
<p class="error-text">${this.props.error || ""}</p>
` : null}
<button disabled=${this.props.disabled}>Connect</button> <button disabled=${this.props.disabled}>Connect</button>
</form> </form>
`; `;

View file

@ -36,11 +36,10 @@ export default class Client extends EventTarget {
try { try {
this.ws = new WebSocket(params.url); this.ws = new WebSocket(params.url);
} catch (err) { } catch (err) {
console.error("Failed to create connection:", err); this.dispatchEvent(new CustomEvent("error", { detail: "Failed to create connection: " + err }));
setTimeout(() => this.dispatchEvent(new CustomEvent("close")), 0); setTimeout(() => this.dispatchEvent(new CustomEvent("close")), 0);
return; return;
} }
this.ws.addEventListener("open", this.handleOpen.bind(this)); this.ws.addEventListener("open", this.handleOpen.bind(this));
this.ws.addEventListener("message", this.handleMessage.bind(this)); this.ws.addEventListener("message", this.handleMessage.bind(this));
@ -50,7 +49,7 @@ export default class Client extends EventTarget {
}); });
this.ws.addEventListener("error", () => { this.ws.addEventListener("error", () => {
console.error("Connection error"); this.dispatchEvent(new CustomEvent("error", { detail: "Connection Error" }));
}); });
} }
@ -95,7 +94,7 @@ export default class Client extends EventTarget {
this.registered = true; this.registered = true;
break; break;
case irc.ERR_PASSWDMISMATCH: case irc.ERR_PASSWDMISMATCH:
console.error("Password mismatch"); this.dispatchEvent(new CustomEvent("error", { detail: "Password mismatch" }));
this.close(); this.close();
break; break;
case "CAP": case "CAP":
@ -121,7 +120,7 @@ export default class Client extends EventTarget {
case irc.ERR_SASLTOOLONG: case irc.ERR_SASLTOOLONG:
case irc.ERR_SASLABORTED: case irc.ERR_SASLABORTED:
case irc.ERR_SASLALREADY: case irc.ERR_SASLALREADY:
console.error("SASL error:", msg); this.dispatchEvent(new CustomEvent("error", { detail: "SASL error: " + msg }));
this.close(); this.close();
break; break;
case "PING": case "PING":
@ -258,7 +257,7 @@ export default class Client extends EventTarget {
// For now only PLAIN is supported // For now only PLAIN is supported
if (challengeStr != "+") { if (challengeStr != "+") {
console.error("Expected an empty challenge, got:", challengeStr); this.dispatchEvent(new CustomEvent("error", { detail: "Expected an empty challenge, got: " + challengeStr }));
this.send({ command: "AUTHENTICATE", params: ["*"] }); this.send({ command: "AUTHENTICATE", params: ["*"] });
return; return;
} }

View file

@ -234,3 +234,22 @@ details summary {
#buffer .nick-16 { #buffer .nick-16 {
color: #ec273e; color: #ec273e;
} }
#error-msg {
color: white;
background-color: red;
position: fixed;
bottom: 2rem;
right: 0;
padding: 0.5rem;
margin: 0.5rem;
}
#error-msg a {
color: white;
text-decoration: none;
}
.error-text {
color: red;
}