Add "open" URL param

This can be set to an irc:// URL to open. This is useful for
bouncers.
This commit is contained in:
Simon Ser 2021-11-08 12:33:02 +01:00
parent 14031c594b
commit f3c48a3748
2 changed files with 64 additions and 17 deletions

View File

@ -83,6 +83,7 @@ gamja settings can be overridden using URL query parameters:
- `server`: path or URL to the WebSocket server
- `nick`: nickname
- `channels`: comma-separated list of channels to join (`#` needs to be escaped)
- `open`: [IRC URL] to open
Alternatively, the channels can be set with the URL fragment (ie, by just
appending the channel name to the gamja URL).
@ -134,3 +135,4 @@ Copyright (C) 2020 The gamja Contributors
[mailing list]: https://lists.sr.ht/~emersion/public-inbox
[issue tracker]: https://todo.sr.ht/~emersion/gamja
[Parcel]: https://parceljs.org
[IRC URL]: https://datatracker.ietf.org/doc/html/draft-butcher-irc-url-04

View File

@ -146,6 +146,11 @@ export default class App extends Component {
buffer = createRef();
composer = createRef();
switchToChannel = null;
/**
* Parsed irc:// URL to automatically open. The user will be prompted for
* confirmation for security reasons.
*/
autoOpenURL = null;
constructor(props) {
super(props);
@ -243,6 +248,10 @@ export default class App extends Component {
connectParams.autojoin = queryParams.channels.split(",");
}
if (typeof queryParams.open === "string") {
this.autoOpenURL = irc.parseURL(queryParams.open);
}
if (window.location.hash) {
connectParams.autojoin = window.location.hash.split(",");
}
@ -798,6 +807,12 @@ export default class App extends Component {
params: [join.join(",")],
});
}
let serverHost = bouncerNetwork ? bouncerNetwork.host : "";
if (this.autoOpenURL && serverHost === this.autoOpenURL.host) {
this.openURL(this.autoOpenURL);
this.autoOpenURL = null;
}
case "JOIN":
channel = msg.params[0];
@ -872,6 +887,24 @@ export default class App extends Component {
}
});
break;
case "BATCH":
if (!msg.params[0].startsWith("-")) {
break;
}
let name = msg.params[0].slice(1);
let batch = client.batches.get(name);
if (!batch || batch.type !== "soju.im/bouncer-networks") {
break;
}
// We've received a BOUNCER NETWORK batch. If we have a URL to
// auto-open and no existing network matches it, ask the user to
// create a new network.
if (this.autoOpenURL && this.autoOpenURL.host && !this.findBouncerNetIDByHost(this.autoOpenURL.host)) {
this.openURL(this.autoOpenURL);
this.autoOpenURL = null;
}
break;
default:
if (irc.isError(msg.command) && msg.command != irc.ERR_NOMOTD) {
let description = msg.params[msg.params.length - 1];
@ -903,31 +936,44 @@ export default class App extends Component {
}
handleChannelClick(event) {
let url = irc.parseURL(event.target.href);
let handled = this.openURL(event.target.href);
if (handled) {
event.preventDefault();
}
}
findBouncerNetIDByHost(host) {
for (let [id, bouncerNetwork] of this.state.bouncerNetworks) {
if (bouncerNetwork.host === host) {
return id;
}
}
return null;
}
openURL(url) {
if (typeof url === "string") {
url = irc.parseURL(url);
}
if (!url) {
return;
return false;
}
let serverID;
if (!url.host) {
serverID = State.getActiveServerID(this.state);
} else {
let bouncerNetID;
for (let [id, bouncerNetwork] of this.state.bouncerNetworks) {
if (bouncerNetwork.host === url.host) {
bouncerNetID = id;
break;
}
}
let bouncerNetID = this.findBouncerNetIDByHost(url.host);
if (!bouncerNetID) {
// Open dialog to create network if bouncer
let client = this.clients.values().next().value;
if (client && client.enabledCaps["soju.im/bouncer-networks"]) {
event.preventDefault();
let params = { host: url.host };
this.openDialog("network", { params, autojoin: url.entity });
if (!client || !client.enabledCaps["soju.im/bouncer-networks"]) {
return false;
}
return;
let params = { host: url.host };
this.openDialog("network", { params, autojoin: url.entity });
return true;
}
for (let [id, server] of this.state.servers) {
@ -938,17 +984,16 @@ export default class App extends Component {
}
}
if (!serverID) {
return;
return false;
}
event.preventDefault();
let buf = State.getBuffer(this.state, { server: serverID, name: url.entity || SERVER_BUFFER });
if (buf) {
this.switchBuffer(buf.id);
} else {
this.openDialog("join", { server: serverID, channel: url.entity });
}
return true;
}
handleNickClick(nick) {