mirror of
https://github.com/thelounge/thelounge.git
synced 2026-08-04 09:02:06 -04:00
Updated version of #4550. Closes #337, closes #872 (#337 can't be fully addressed — tracking nick changes isn't really possible atm). <img width="253" height="149" alt="image" src="https://github.com/user-attachments/assets/8a961868-0aa9-406b-92e2-f9d4858e2d0d" /> Away support: <img width="214" alt="image" src="https://user-images.githubusercontent.com/8675906/165882385-6f928c8e-5a0b-4502-8bd3-3cd0bd70e0e0.png"> ## Summary Query windows show whether the person behind them is online, and whether they are away, using [MONITOR](https://ircv3.net/specs/extensions/monitor) rather than polling. `Network` keeps the monitor list: queries are registered in batched `MONITOR +` commands once RPL_ISUPPORT tells us the server supports it, and one at a time as new query windows open. The limit advertised in `MONITOR=<n>` is respected, with anything over it waiting for a slot; `MONITOR=0` means no monitoring at all, a bare `MONITOR` means no limit. A nick change on a monitored query swaps the target in place so the query keeps its slot. [extended-monitor](https://ircv3.net/specs/extensions/extended-monitor) is requested too, so away, nick, account and chghost updates arrive for monitored nicks we share no channel with. Away state for people we do share a channel with comes from a WHO on join. The indicator is a dot on the query in the sidebar and next to the nick in the message bubble, with a tooltip and an `img` role so it isn't colour-only, and it can be turned off under Appearance. Known limitation: a server that enforces a monitor limit it doesn't advertise will reject part of a batch with `ERR_MONLISTFULL`; the user gets a message in the lobby, but the client's own list isn't reconciled until reconnect. ## Test Plan - Unit tests for the monitor list: add, case-insensitive dedupe, queueing at the limit, removal draining the queue, batching, and the rename path. - Ran the server against a local IRCd and watched the wire: opening queries sends `MONITOR + <nick>` each, a reconnect with four open queries sends a single `MONITOR + bob,carol,dave,mallory`, 730/731 drive the online/offline state, a rename sends `MONITOR - bob` then `MONITOR + bob2`, `MONITOR=0` sends nothing at all, and a bare `MONITOR` behaves as unlimited.
49 lines
976 B
TypeScript
49 lines
976 B
TypeScript
import _ from "lodash";
|
|
import Prefix from "./prefix";
|
|
|
|
class User {
|
|
modes!: string[];
|
|
// Users in the channel have only one mode assigned
|
|
mode!: string;
|
|
away!: string;
|
|
nick!: string;
|
|
lastMessage!: number;
|
|
isBot!: boolean;
|
|
|
|
constructor(attr: Partial<User>, prefix?: Prefix) {
|
|
_.defaults(this, attr, {
|
|
modes: [],
|
|
away: "",
|
|
nick: "",
|
|
lastMessage: 0,
|
|
isBot: false,
|
|
});
|
|
|
|
Object.defineProperty(this, "mode", {
|
|
get() {
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
return this.modes[0] || "";
|
|
},
|
|
});
|
|
|
|
this.setModes(this.modes, prefix || new Prefix([]));
|
|
}
|
|
|
|
setModes(modes: string[], prefix: Prefix) {
|
|
// irc-framework sets character mode, but The Lounge works with symbols
|
|
this.modes = modes.map((mode) => prefix.modeToSymbol[mode]);
|
|
}
|
|
|
|
toJSON() {
|
|
return {
|
|
nick: this.nick,
|
|
modes: this.modes,
|
|
away: this.away,
|
|
lastMessage: this.lastMessage,
|
|
isBot: this.isBot,
|
|
};
|
|
}
|
|
}
|
|
|
|
export default User;
|