diff --git a/components/app.js b/components/app.js index 4985d74..0a4be12 100644 --- a/components/app.js +++ b/components/app.js @@ -865,13 +865,46 @@ export default class App extends Component { this.connect(connectParams); } - handleChannelClick(channel) { - let serverID = State.getActiveServerID(this.state); - let buf = State.getBuffer(this.state, { server: serverID, name: channel }); + handleChannelClick(event) { + let url = irc.parseURL(event.target.href); + if (!url) { + return; + } + + 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; + } + } + if (!bouncerNetID) { + // TODO: open dialog to create network if bouncer + return; + } + + for (let [id, server] of this.state.servers) { + if (server.isupport.get("BOUNCER_NETID") === bouncerNetID) { + serverID = id; + break; + } + } + } + if (!serverID) { + return; + } + + event.preventDefault(); + + let buf = State.getBuffer(this.state, { server: serverID, name: url.channel }); if (buf) { this.switchBuffer(buf.id); } else { - this.open(channel); + this.open(url.channel, serverID); } } diff --git a/lib/irc.js b/lib/irc.js index f1f0817..95b7860 100644 --- a/lib/irc.js +++ b/lib/irc.js @@ -656,3 +656,27 @@ export function isMeaningfulRealname(realname, nick) { return true; } + +export function parseURL(str) { + if (!str.startsWith("irc://") && !str.startsWith("ircs://")) { + return null; + } + + str = str.slice(str.indexOf(":") + 3); + + let i = str.indexOf("/"); + if (i < 0) { + return null; + } + + let host = str.slice(0, i); + str = str.slice(i + 1); + + // TODO: handle URLs with query params + if (!str.startsWith("#")) { + return null; + } + let channel = str; + + return { host, channel }; +} diff --git a/lib/linkify.js b/lib/linkify.js index b8623fe..6004a31 100644 --- a/lib/linkify.js +++ b/lib/linkify.js @@ -5,11 +5,11 @@ linkifyjs.options.defaults.defaultProtocol = "https"; linkifyjs.registerCustomProtocol("irc"); linkifyjs.registerCustomProtocol("ircs"); -linkifyjs.registerPlugin('ircChannel', ({ scanner, parser, utils }) => { +linkifyjs.registerPlugin("ircChannel", ({ scanner, parser, utils }) => { const { POUND, DOMAIN, TLD, LOCALHOST, UNDERSCORE, DOT, HYPHEN } = scanner.tokens; const START_STATE = parser.start; - const Channel = utils.createTokenClass('ircChannel', { + const Channel = utils.createTokenClass("ircChannel", { isLink: true, toHref() { return "irc:///" + this.toString(); @@ -36,7 +36,7 @@ linkifyjs.registerPlugin('ircChannel', ({ scanner, parser, utils }) => { CHAN_DIVIDER_STATE.tt(LOCALHOST, CHAN_STATE); }); -export default function linkify(text, onChannelClick) { +export default function linkify(text, onClick) { let links = linkifyjs.find(text); let children = []; @@ -49,27 +49,14 @@ export default function linkify(text, onChannelClick) { const prefix = text.substring(last, match.start) children.push(prefix); - // TODO: handle all irc/ircs URLs - if (match.href.startsWith("irc:///")) { - function onClick(event) { - event.preventDefault(); - onChannelClick(match.value); - } - children.push(html` - ${match.value} - `); - } else { - children.push(html` - ${match.value} - `); - } + children.push(html` + ${match.value} + `); last = match.end; });