From abece1e3fd3563c2b9c407b1559d0dae3e1d9fbd Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 29 Jun 2020 11:08:47 +0200 Subject: [PATCH] Detect highlights --- components/app.js | 7 ++++++- lib/irc.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ state.js | 2 ++ style.css | 3 +++ 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/components/app.js b/components/app.js index bce9797..6cc82dc 100644 --- a/components/app.js +++ b/components/app.js @@ -168,7 +168,12 @@ export default class App extends Component { var msgUnread = Unread.NONE; if (msg.command == "PRIVMSG" || msg.command == "NOTICE") { - msgUnread = Unread.MESSAGE; + var text = msg.params[1]; + if (msg.prefix.name != this.client.nick && irc.isHighlight(text, this.client.nick)) { + msgUnread = Unread.HIGHLIGHT; + } else { + msgUnread = Unread.MESSAGE; + } } if (msg.prefix.name != this.client.nick && msg.command != "PART") { diff --git a/lib/irc.js b/lib/irc.js index fab7e97..e7bac49 100644 --- a/lib/irc.js +++ b/lib/irc.js @@ -196,3 +196,47 @@ export function parseMembership(s) { nick: s.slice(i), }; } + +const alphaNum = (() => { + try { + return new RegExp(/^\p{L}$/, "u"); + } catch (e) { + return new RegExp(/^[a-zA-Z0-9]$/, "u"); + } +})(); + +function isWordBoundary(ch) { + switch (ch) { + case "-": + case "_": + case "|": + return false; + case "\u00A0": + return true; + default: + return !alphaNum.test(ch); + } +} + +export function isHighlight(text, nick) { + while (true) { + var i = text.indexOf(nick); + if (i < 0) { + return false; + } + + // Detect word boundaries + var left = "\x00", right = "\x00"; + if (i > 0) { + left = text[i - 1]; + } + if (i < text.length) { + right = text[i + nick.length]; + } + if (isWordBoundary(left) && isWordBoundary(right)) { + return true; + } + + text = text.slice(i + nick.length); + } +} diff --git a/state.js b/state.js index ee0f7b1..4ef6567 100644 --- a/state.js +++ b/state.js @@ -13,11 +13,13 @@ export const Status = { export const Unread = { NONE: "", MESSAGE: "message", + HIGHLIGHT: "highlight", union: (a, b) => { const priority = { [Unread.None]: 0, [Unread.MESSAGE]: 1, + [Unread.HIGHLIGHT]: 2, }; return (priority[a] > priority[b]) ? a : b; }, diff --git a/style.css b/style.css index b531203..c68b710 100644 --- a/style.css +++ b/style.css @@ -46,6 +46,9 @@ body { #buffer-list li.unread-message a { color: #b37400; } +#buffer-list li.unread-highlight a { + color: #22009b; +} #buffer-list .actions { flex-shrink: 0; text-align: center;