diff --git a/components/app.js b/components/app.js
index 01799f1..31529e0 100644
--- a/components/app.js
+++ b/components/app.js
@@ -98,6 +98,7 @@ export default class App extends Component {
status: Status.DISCONNECTED,
buffers: new Map(),
activeBuffer: null,
+ error: null,
};
pendingHistory = Promise.resolve(null);
endOfHistory = new Map();
@@ -115,6 +116,7 @@ export default class App extends Component {
this.handleJoinClick = this.handleJoinClick.bind(this);
this.autocomplete = this.autocomplete.bind(this);
this.handleBufferScrollTop = this.handleBufferScrollTop.bind(this);
+ this.dismissError = this.dismissError.bind(this);
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) {
this.setState((state) => {
var buf = state.buffers.get(name);
@@ -353,6 +360,12 @@ export default class App extends Component {
this.handleMessage(event.detail.message);
});
+ this.client.addEventListener("error", (event) => {
+ this.setState({
+ error: event.detail,
+ });
+ });
+
this.createBuffer(SERVER_BUFFER);
this.switchBuffer(SERVER_BUFFER);
}
@@ -461,7 +474,7 @@ export default class App extends Component {
var after = receipt;
var before = { time: msg.tags.time || irc.formatDate(new Date()) };
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.saveReceipts();
});
@@ -605,20 +618,20 @@ export default class App extends Component {
var cmd = commands[name];
if (!cmd) {
- console.error("Unknwon command '" + name + "'");
+ this.setState({ error: "Unknown command '" + name + "'" });
return;
}
try {
cmd(this, args);
- } catch (err) {
- console.error(err);
+ } catch (error) {
+ this.setState({ error });
}
}
privmsg(target, text) {
if (target == SERVER_BUFFER) {
- console.error("Cannot send message in server buffer");
+ this.setState({ error: "Cannot send message in server buffer" });
return;
}
@@ -787,7 +800,7 @@ export default class App extends Component {
if (this.state.status != Status.REGISTERED) {
return html`
${this.state.error} ×
+ ` : null} `; } } diff --git a/components/connect.js b/components/connect.js index 97589e0..94ea120 100644 --- a/components/connect.js +++ b/components/connect.js @@ -140,7 +140,9 @@ export default class Connect extends Component {${this.props.error || ""}
+ ` : null} `; diff --git a/lib/client.js b/lib/client.js index 01fd67b..4c093e9 100644 --- a/lib/client.js +++ b/lib/client.js @@ -36,11 +36,10 @@ export default class Client extends EventTarget { try { this.ws = new WebSocket(params.url); } 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); return; } - this.ws.addEventListener("open", this.handleOpen.bind(this)); this.ws.addEventListener("message", this.handleMessage.bind(this)); @@ -50,7 +49,7 @@ export default class Client extends EventTarget { }); 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; break; case irc.ERR_PASSWDMISMATCH: - console.error("Password mismatch"); + this.dispatchEvent(new CustomEvent("error", { detail: "Password mismatch" })); this.close(); break; case "CAP": @@ -121,7 +120,7 @@ export default class Client extends EventTarget { case irc.ERR_SASLTOOLONG: case irc.ERR_SASLABORTED: case irc.ERR_SASLALREADY: - console.error("SASL error:", msg); + this.dispatchEvent(new CustomEvent("error", { detail: "SASL error: " + msg })); this.close(); break; case "PING": @@ -258,7 +257,7 @@ export default class Client extends EventTarget { // For now only PLAIN is supported 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: ["*"] }); return; } diff --git a/style.css b/style.css index 3d1166f..c1fdd5a 100644 --- a/style.css +++ b/style.css @@ -234,3 +234,22 @@ details summary { #buffer .nick-16 { 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; +}