mirror of
https://github.com/thelounge/thelounge.git
synced 2026-07-30 22:55:50 -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.
80 lines
1.4 KiB
Vue
80 lines
1.4 KiB
Vue
<template>
|
|
<div
|
|
:class="['status-icon', 'tooltipped tooltipped-no-touch', tooltipDirClass]"
|
|
:data-tooltip="label"
|
|
role="img"
|
|
:aria-label="label"
|
|
>
|
|
<span :class="statusClass" />
|
|
</div>
|
|
</template>
|
|
|
|
<style>
|
|
.status-icon {
|
|
width: 16px;
|
|
height: 16px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
margin-left: 4px;
|
|
z-index: 0;
|
|
}
|
|
|
|
.status-icon > span::after {
|
|
content: "";
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
display: inline-block;
|
|
}
|
|
|
|
.status-icon > .status-online::after {
|
|
background-color: #2ecc40;
|
|
}
|
|
|
|
.status-icon > .status-offline::after {
|
|
background-color: #ff4136;
|
|
}
|
|
|
|
.status-icon > .status-away::after {
|
|
background-color: gray;
|
|
}
|
|
</style>
|
|
|
|
<script lang="ts">
|
|
import {computed, PropType, defineComponent} from "vue";
|
|
|
|
export default defineComponent({
|
|
name: "StatusIcon",
|
|
props: {
|
|
online: Boolean,
|
|
away: Boolean,
|
|
tooltipDir: String as PropType<"n" | "s" | "e" | "w">,
|
|
},
|
|
setup(props) {
|
|
const tooltipDirClass = computed(
|
|
() => `tooltipped-${props.tooltipDir ? props.tooltipDir : "w"}`
|
|
);
|
|
|
|
const label = computed(() => {
|
|
if (props.away) {
|
|
return "Away";
|
|
} else if (props.online) {
|
|
return "Online";
|
|
}
|
|
|
|
return "Offline";
|
|
});
|
|
|
|
const statusClass = computed(() => `status-${label.value.toLowerCase()}`);
|
|
|
|
return {
|
|
tooltipDirClass,
|
|
statusClass,
|
|
label,
|
|
};
|
|
},
|
|
});
|
|
</script>
|