Linkify channel names

This commit is contained in:
Tom Lebreux 2021-05-31 22:39:35 -04:00 committed by Simon Ser
parent 9affdb894f
commit 0bcd044f10
4 changed files with 62 additions and 8 deletions

View file

@ -225,6 +225,7 @@ export default class App extends Component {
this.toggleBufferList = this.toggleBufferList.bind(this);
this.toggleMemberList = this.toggleMemberList.bind(this);
this.handleComposerSubmit = this.handleComposerSubmit.bind(this);
this.handleChannelClick = this.handleChannelClick.bind(this);
this.handleNickClick = this.handleNickClick.bind(this);
this.autocomplete = this.autocomplete.bind(this);
this.handleBufferScrollTop = this.handleBufferScrollTop.bind(this);
@ -908,6 +909,16 @@ export default class App extends Component {
this.connect(connectParams);
}
handleChannelClick(channel) {
var netID = getActiveNetworkID(this.state);
var buf = getBuffer(this.state, { network: netID, name: channel });
if (buf) {
this.switchBuffer(buf.id);
} else {
this.open(channel);
}
}
handleNickClick(nick) {
this.open(nick);
}
@ -1361,6 +1372,7 @@ export default class App extends Component {
network=${activeNetwork}
isBouncer=${isBouncer}
bouncerNetwork=${activeBouncerNetwork}
onChannelClick=${this.handleChannelClick}
onClose=${() => this.close(activeBuffer)}
onJoin=${() => this.handleJoinClick(activeBuffer.network)}
onAddNetwork=${this.handleAddNetworkClick}
@ -1475,7 +1487,10 @@ export default class App extends Component {
onScrollTop=${this.handleBufferScrollTop}
>
<section id="buffer" ref=${this.buffer}>
<${Buffer} buffer=${activeBuffer} onNickClick=${this.handleNickClick}/>
<${Buffer}
buffer=${activeBuffer}
onChannelClick=${this.handleChannelClick}
onNickClick=${this.handleNickClick}/>
</section>
</>
${memberList}

View file

@ -114,7 +114,7 @@ export default function BufferHeader(props) {
break;
case BufferType.CHANNEL:
if (props.buffer.topic) {
description = linkify(stripANSI(props.buffer.topic));
description = linkify(stripANSI(props.buffer.topic), props.onChannelClick);
}
actions = html`
<button

View file

@ -64,6 +64,7 @@ class LogLine extends Component {
render() {
var msg = this.props.message;
var onChannelClick = this.props.onChannelClick;
var onNickClick = this.props.onNickClick;
function createNick(nick) {
return html`
@ -82,7 +83,7 @@ class LogLine extends Component {
if (ctcp) {
if (ctcp.command == "ACTION") {
lineClass = "me-tell";
content = html`* ${createNick(msg.prefix.name)} ${linkify(stripANSI(ctcp.param))}`;
content = html`* ${createNick(msg.prefix.name)} ${linkify(stripANSI(ctcp.param), onChannelClick)}`;
} else {
content = html`
${createNick(msg.prefix.name)} has sent a CTCP command: ${ctcp.command} ${ctcp.param}
@ -94,7 +95,7 @@ class LogLine extends Component {
if (msg.command == "NOTICE") {
prefix = suffix = "-";
}
content = html`${prefix}${createNick(msg.prefix.name)}${suffix} ${linkify(stripANSI(text))}`;
content = html`${prefix}${createNick(msg.prefix.name)}${suffix} ${linkify(stripANSI(text), onChannelClick)}`;
}
if (msg.isHighlight) {
@ -135,7 +136,7 @@ class LogLine extends Component {
case "TOPIC":
var topic = msg.params[1];
content = html`
${createNick(msg.prefix.name)} changed the topic to: ${linkify(stripANSI(topic))}
${createNick(msg.prefix.name)} changed the topic to: ${linkify(stripANSI(topic), onChannelClick)}
`;
break;
case irc.RPL_MOTD:
@ -364,6 +365,7 @@ export default class Buffer extends Component {
children.push(html`<${NotificationNagger}/>`);
}
var onChannelClick = this.props.onChannelClick;
var onNickClick = this.props.onNickClick;
function createLogLine(msg) {
return html`
@ -371,6 +373,7 @@ export default class Buffer extends Component {
key=${"msg-" + msg.key}
message=${msg}
buffer=${buf}
onChannelClick=${onChannelClick}
onNickClick=${onNickClick}
/>
`;

View file

@ -1,12 +1,46 @@
import { anchorme, html } from "./index.js";
export default function linkify(text) {
function linkifyChannel(text, transformChannel) {
var children = [];
// TODO: Don't match punctuation
const channelRegex = /(^|\s)(#[^\s]+)/gid;
let match;
var last = 0;
while ((match = channelRegex.exec(text)) !== null) {
const [_, spaces, channel] = match;
const start = match.index + spaces.length;
children.push(text.substring(last, start));
children.push(transformChannel(channel));
last = match.index + spaces.length + channel.length;
}
children.push(text.substring(last));
return children;
}
export default function linkify(text, onChannelClick) {
function transformChannel(channel) {
function onClick(event) {
event.preventDefault();
onChannelClick(channel);
}
return html`
<a
href="irc:///${encodeURIComponent(channel)}"
onClick=${onClick}
>${channel}</a>`;
}
var links = anchorme.list(text);
var children = [];
var last = 0;
links.forEach((match) => {
children.push(text.substring(last, match.start));
const prefix = text.substring(last, match.start)
children.push(...linkifyChannel(prefix, transformChannel));
var proto = match.protocol || "https://";
if (match.isEmail) {
@ -22,7 +56,9 @@ export default function linkify(text) {
last = match.end;
});
children.push(text.substring(last));
const suffix = text.substring(last)
children.push(...linkifyChannel(suffix, transformChannel));
return children;
}