diff --git a/components/app.js b/components/app.js index 22e393f..26a3fee 100644 --- a/components/app.js +++ b/components/app.js @@ -1234,11 +1234,17 @@ export default class App extends Component { let bufferHeader = null; if (activeBuffer) { + let activeUser = null; + if (activeBuffer.type == BufferType.NICK) { + activeUser = activeServer.users.get(activeBuffer.name); + } + bufferHeader = html`
<${BufferHeader} buffer=${activeBuffer} server=${activeServer} + user=${activeUser} isBouncer=${isBouncer} bouncerNetwork=${activeBouncerNetwork} onChannelClick=${this.handleChannelClick} diff --git a/components/buffer-header.js b/components/buffer-header.js index a4def90..0eceb66 100644 --- a/components/buffer-header.js +++ b/components/buffer-header.js @@ -125,23 +125,25 @@ export default function BufferHeader(props) { `; break; case BufferType.NICK: - if (props.buffer.who) { - let who = props.buffer.who; - - let realname = stripANSI(who.realname || ""); - + if (props.user) { let status = UserStatus.HERE; - if (who.away) { + if (props.user.offline) { + status = UserStatus.OFFLINE; + } else if (props.user.away) { status = UserStatus.GONE; } - if (props.buffer.offline) { - status = UserStatus.OFFLINE; + + let realname = props.buffer.name; + if (props.user.realname) { + realname = stripANSI(props.user.realname || ""); } - description = html`<${NickStatus} status=${status}/> ${realname} (${who.username}@${who.hostname})`; - } else if (props.buffer.offline) { - // User is offline, but we don't have WHO information - description = html`<${NickStatus} status=${UserStatus.OFFLINE}/> ${props.buffer.name}`; + let mask = null; + if (props.user.username && props.user.hostname) { + mask = `(${props.user.username}@${props.user.hostname})`; + } + + description = html`<${NickStatus} status=${status}/> ${realname} ${mask}`; } actions = html` diff --git a/state.js b/state.js index 9e46d30..613c709 100644 --- a/state.js +++ b/state.js @@ -248,6 +248,7 @@ export const State = { id, status: ServerStatus.DISCONNECTED, isupport: new Map(), + users: new irc.CaseMapMap(null, irc.CaseMapping.RFC1459), }); return [id, { servers }]; }, @@ -278,8 +279,6 @@ export const State = { serverInfo: null, // if server topic: null, // if channel members: new irc.CaseMapMap(null, client.cm), // if channel - who: null, // if nick - offline: false, // if nick messages: [], unread: Unread.NONE, prevReadReceipt: null, @@ -295,6 +294,17 @@ export const State = { function updateBuffer(name, updater) { return State.updateBuffer(state, { server: serverID, name }, updater); } + function updateUser(name, updater) { + return updateServer((server) => { + let users = new irc.CaseMapMap(server.users); + let updated = updateState(users.get(name), updater); + if (!updated) { + return; + } + users.set(name, updated); + return { users }; + }); + } // Don't update our internal state if it's a chat history message if (irc.findBatchByType(msg, "chathistory")) { @@ -321,7 +331,12 @@ export const State = { }); return { buffers, - ...updateServer({ isupport: new Map(client.isupport) }), + ...updateServer((server) => { + return { + isupport: new Map(client.isupport), + users: new irc.CaseMapMap(server.users, client.cm), + }; + }), }; case irc.RPL_NOTOPIC: channel = msg.params[1]; @@ -356,16 +371,17 @@ export const State = { nick: msg.params[5], away: msg.params[6] == 'G', // H for here, G for gone realname: last.slice(last.indexOf(" ") + 1), + offline: false, }; - return updateBuffer(who.nick, { who, offline: false }); + return updateUser(who.nick, who); case irc.RPL_ENDOFWHO: target = msg.params[1]; if (!client.isChannel(target) && target.indexOf("*") < 0) { // Not a channel nor a mask, likely a nick - return updateBuffer(target, (buf) => { + return updateUser(target, (user) => { // TODO: mark user offline if we have old WHO info but this // WHO reply is empty - if (buf.who) { + if (user) { return; } return { offline: true }; @@ -404,26 +420,15 @@ export const State = { return { members }; }); case "SETNAME": - return updateBuffer(msg.prefix.name, (buf) => { - let who = { ...buf.who, realname: msg.params[0] }; - return { who }; - }); + return updateUser(msg.prefix.name, { realname: msg.params[0] }); case "CHGHOST": - return updateBuffer(msg.prefix.name, (buf) => { - let who = { - ...buf.who, - username: msg.params[0], - hostname: msg.params[1], - }; - return { who }; + return updateUser(msg.prefix.name, { + username: msg.params[0], + hostname: msg.params[1], }); case "AWAY": let awayMessage = msg.params[0]; - - return updateBuffer(msg.prefix.name, (buf) => { - let who = { ...buf.who, away: !!awayMessage }; - return { who }; - }); + return updateUser(msg.prefix.name, { away: !!awayMessage }); case "TOPIC": channel = msg.params[0]; topic = msg.params[1]; @@ -459,9 +464,7 @@ export const State = { for (let target of targets) { let prefix = irc.parsePrefix(target); - let update = updateBuffer(prefix.name, (buf) => { - return { offline: false }; - }); + let update = updateUser(prefix.name, { offline: false }); state = { ...state, ...update }; } @@ -471,9 +474,7 @@ export const State = { for (let target of targets) { let prefix = irc.parsePrefix(target); - let update = updateBuffer(prefix.name, (buf) => { - return { offline: true }; - }); + let update = updateUser(prefix.name, { offline: true }); state = { ...state, ...update }; }