Handle click on irc:// channel URLs inside buffers

References: https://todo.sr.ht/~emersion/gamja/71
This commit is contained in:
Simon Ser 2021-10-13 16:18:59 +02:00
parent 631f119061
commit 405bc51c26
3 changed files with 72 additions and 28 deletions

View File

@ -865,13 +865,46 @@ export default class App extends Component {
this.connect(connectParams); this.connect(connectParams);
} }
handleChannelClick(channel) { handleChannelClick(event) {
let serverID = State.getActiveServerID(this.state); let url = irc.parseURL(event.target.href);
let buf = State.getBuffer(this.state, { server: serverID, name: channel }); 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) { if (buf) {
this.switchBuffer(buf.id); this.switchBuffer(buf.id);
} else { } else {
this.open(channel); this.open(url.channel, serverID);
} }
} }

View File

@ -656,3 +656,27 @@ export function isMeaningfulRealname(realname, nick) {
return true; 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 };
}

View File

@ -5,11 +5,11 @@ linkifyjs.options.defaults.defaultProtocol = "https";
linkifyjs.registerCustomProtocol("irc"); linkifyjs.registerCustomProtocol("irc");
linkifyjs.registerCustomProtocol("ircs"); 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 { POUND, DOMAIN, TLD, LOCALHOST, UNDERSCORE, DOT, HYPHEN } = scanner.tokens;
const START_STATE = parser.start; const START_STATE = parser.start;
const Channel = utils.createTokenClass('ircChannel', { const Channel = utils.createTokenClass("ircChannel", {
isLink: true, isLink: true,
toHref() { toHref() {
return "irc:///" + this.toString(); return "irc:///" + this.toString();
@ -36,7 +36,7 @@ linkifyjs.registerPlugin('ircChannel', ({ scanner, parser, utils }) => {
CHAN_DIVIDER_STATE.tt(LOCALHOST, CHAN_STATE); 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 links = linkifyjs.find(text);
let children = []; let children = [];
@ -49,27 +49,14 @@ export default function linkify(text, onChannelClick) {
const prefix = text.substring(last, match.start) const prefix = text.substring(last, match.start)
children.push(prefix); 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`
<a
href="${match.href}"
onClick=${onClick}
>${match.value}</a>
`);
} else {
children.push(html` children.push(html`
<a <a
href=${match.href} href=${match.href}
target="_blank" target="_blank"
rel="noreferrer noopener" rel="noreferrer noopener"
onClick=${onClick}
>${match.value}</a> >${match.value}</a>
`); `);
}
last = match.end; last = match.end;
}); });