diff --git a/components/app.js b/components/app.js
index 0f55d68..5fc2034 100644
--- a/components/app.js
+++ b/components/app.js
@@ -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}
>
- <${Buffer} buffer=${activeBuffer} onNickClick=${this.handleNickClick}/>
+ <${Buffer}
+ buffer=${activeBuffer}
+ onChannelClick=${this.handleChannelClick}
+ onNickClick=${this.handleNickClick}/>
>
${memberList}
diff --git a/components/buffer-header.js b/components/buffer-header.js
index 4fe0835..586c467 100644
--- a/components/buffer-header.js
+++ b/components/buffer-header.js
@@ -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`
`);
}
+ 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}
/>
`;
diff --git a/lib/linkify.js b/lib/linkify.js
index c9697cd..aee4512 100644
--- a/lib/linkify.js
+++ b/lib/linkify.js
@@ -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`
+ ${channel}`;
+ }
+
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;
}