diff options
-rw-r--r-- | README.md | 5 | ||||
-rw-r--r-- | components/buffer.js | 75 | ||||
-rw-r--r-- | components/member-list.js | 19 | ||||
-rw-r--r-- | components/membership.js | 15 | ||||
-rw-r--r-- | lib/irc.js | 20 | ||||
-rw-r--r-- | style.css | 2 |
6 files changed, 98 insertions, 38 deletions
@@ -45,8 +45,8 @@ gamja can be configured via a [configuration file] and via [URL parameters]. ## Contributing -Send patches on the [mailing list], report bugs on the [issue tracker]. Discuss -in [#soju on Libera Chat]. +Send patches on [Codeberg] or on the [mailing list], report bugs on the +[issue tracker]. Discuss in [#soju on Libera Chat]. ## License @@ -55,6 +55,7 @@ AGPLv3, see LICENSE. Copyright (C) 2020 The gamja Contributors [gamja]: https://sr.ht/~emersion/gamja/ +[Codeberg]: https://codeberg.org/emersion/gamja [mailing list]: https://lists.sr.ht/~emersion/public-inbox [issue tracker]: https://todo.sr.ht/~emersion/gamja [Parcel]: https://parceljs.org diff --git a/components/buffer.js b/components/buffer.js index 3112a57..3b160e3 100644 --- a/components/buffer.js +++ b/components/buffer.js @@ -196,11 +196,80 @@ class LogLine extends Component { break; case "MODE": target = msg.params[0]; + let modeStr = msg.params[1]; + + let user = html`${createNick(msg.prefix.name)}`; + + // TODO: use irc.forEachChannelModeUpdate() + if (buf.type == BufferType.CHANNEL && modeStr.length === 2 && server.cm(buf.name) === server.cm(target)) { + let plusMinus = modeStr[0]; + let mode = modeStr[1]; + let arg = msg.params[2]; + + let verb; + switch (mode) { + case "b": + verb = plusMinus === "+" ? "added" : "removed"; + content = html`${user} has ${verb} a ban on ${arg}`; + break; + case "e": + verb = plusMinus === "+" ? "added" : "removed"; + content = html`${user} has ${verb} a ban exemption on ${arg}`; + break; + case "l": + if (plusMinus === "+") { + content = html`${user} has set the channel user limit to ${arg}`; + } else { + content = html`${user} has unset the channel user limit`; + } + break; + case "i": + verb = plusMinus === "+" ? "marked": "unmarked"; + content = html`${user} has ${verb} as invite-only`; + break; + case "m": + verb = plusMinus === "+" ? "marked": "unmarked"; + content = html`${user} has ${verb} as moderated`; + break; + case "s": + verb = plusMinus === "+" ? "marked": "unmarked"; + content = html`${user} has ${verb} as secret`; + break; + case "t": + verb = plusMinus === "+" ? "locked": "unlocked"; + content = html`${user} has ${verb} the channel topic`; + break; + case "n": + verb = plusMinus === "+" ? "allowed": "denied"; + content = html`${user} has ${verb} external messages to this channel`; + break; + } + if (content) { + break; + } + + // Channel membership modes + let membership; + for (let prefix in irc.STD_MEMBERSHIP_MODES) { + if (irc.STD_MEMBERSHIP_MODES[prefix] === mode) { + membership = irc.STD_MEMBERSHIP_NAMES[prefix]; + break; + } + } + if (membership && arg) { + let verb = plusMinus === "+" ? "granted" : "revoked"; + let preposition = plusMinus === "+" ? "to" : "from"; + content = html` + ${user} has ${verb} ${membership} privileges ${preposition} ${createNick(arg)} + `; + break; + } + } + content = html` - * ${createNick(msg.prefix.name)} sets mode ${msg.params.slice(1).join(" ")} + ${user} sets mode ${msg.params.slice(1).join(" ")} `; - // TODO: case-mapping - if (buf.name !== target) { + if (server.cm(buf.name) !== server.cm(target)) { content = html`${content} on ${target}`; } break; diff --git a/components/member-list.js b/components/member-list.js index 283892d..f539f76 100644 --- a/components/member-list.js +++ b/components/member-list.js @@ -22,25 +22,6 @@ class MemberItem extends Component { } render() { - // XXX: If we were feeling creative we could generate unique colors for - // each item in ISUPPORT CHANMODES. But I am not feeling creative. - const membmap = { - "~": "owner", - "&": "admin", - "@": "op", - "%": "halfop", - "+": "voice", - }; - const membclass = membmap[this.props.membership[0]] || ""; - let membership = ""; - if (this.props.membership) { - membership = html` - <span class="membership ${membclass}" title=${membclass}> - ${this.props.membership} - </span> - `; - }; - let title; let user = this.props.user; let classes = ["nick"]; diff --git a/components/membership.js b/components/membership.js index 36b3d73..9f7b4c3 100644 --- a/components/membership.js +++ b/components/membership.js @@ -1,21 +1,14 @@ import { html, Component } from "../lib/index.js"; - -// XXX: If we were feeling creative we could generate unique colors for -// each item in ISUPPORT CHANMODES. But I am not feeling creative. -const names = { - "~": "owner", - "&": "admin", - "@": "op", - "%": "halfop", - "+": "voice", -}; +import * as irc from "../lib/irc.js"; export default function Membership(props) { if (!this.props.value) { return null; } - const name = names[this.props.value[0]] || ""; + // XXX: If we were feeling creative we could generate unique colors for + // each item in ISUPPORT CHANMODES. But I am not feeling creative. + const name = irc.STD_MEMBERSHIP_NAMES[this.props.value[0]] || ""; return html` <span class="membership ${name}" title=${name}> ${this.props.value} @@ -74,8 +74,24 @@ export const ERR_SASLTOOLONG = "905"; export const ERR_SASLABORTED = "906"; export const ERR_SASLALREADY = "907"; -export const STD_MEMBERSHIPS = "~&@%+"; -export const STD_CHANTYPES = "#&+!"; +export const STD_MEMBERSHIP_NAMES = { + "~": "owner", + "&": "admin", + "@": "operator", + "%": "halfop", + "+": "voice", +}; + +export const STD_MEMBERSHIP_MODES = { + "~": "q", + "&": "a", + "@": "o", + "%": "h", + "+": "v", +}; + +const STD_MEMBERSHIPS = "~&@%+"; +const STD_CHANTYPES = "#&+!"; const tagEscapeMap = { ";": "\\:", @@ -302,7 +302,7 @@ button.danger:hover { .membership.admin { color: blue; } -.membership.op { +.membership.operator { color: var(--green); } .membership.halfop { |