2021-03-02 16:46:48 -05:00
|
|
|
import { html, Component } from "../lib/index.js";
|
|
|
|
import linkify from "../lib/linkify.js";
|
|
|
|
import { strip as stripANSI } from "../lib/ansi.js";
|
2021-06-03 05:46:50 -04:00
|
|
|
import { BufferType, ServerStatus, getServerName } from "../state.js";
|
2021-09-21 11:24:39 -04:00
|
|
|
import * as irc from "../lib/irc.js";
|
2020-06-25 12:30:21 -04:00
|
|
|
|
2021-01-22 05:53:17 -05:00
|
|
|
const UserStatus = {
|
2020-07-13 06:51:09 -04:00
|
|
|
HERE: "here",
|
|
|
|
GONE: "gone",
|
|
|
|
OFFLINE: "offline",
|
|
|
|
};
|
|
|
|
|
|
|
|
function NickStatus(props) {
|
2021-06-10 12:11:11 -04:00
|
|
|
let textMap = {
|
2021-01-22 05:53:17 -05:00
|
|
|
[UserStatus.HERE]: "User is online",
|
|
|
|
[UserStatus.GONE]: "User is away",
|
|
|
|
[UserStatus.OFFLINE]: "User is offline",
|
2020-07-13 06:51:09 -04:00
|
|
|
};
|
2021-06-10 12:11:11 -04:00
|
|
|
let text = textMap[props.status];
|
2020-07-13 06:51:09 -04:00
|
|
|
return html`<span class="status status-${props.status}" title=${text}>●</span>`;
|
|
|
|
}
|
|
|
|
|
2020-06-25 12:30:21 -04:00
|
|
|
export default function BufferHeader(props) {
|
2021-03-09 13:10:22 -05:00
|
|
|
function handleCloseClick(event) {
|
2020-06-25 12:30:21 -04:00
|
|
|
event.preventDefault();
|
|
|
|
props.onClose();
|
|
|
|
}
|
2021-03-02 10:13:49 -05:00
|
|
|
function handleJoinClick(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
props.onJoin();
|
|
|
|
}
|
2021-03-08 12:15:04 -05:00
|
|
|
function handleAddNetworkClick(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
props.onAddNetwork();
|
|
|
|
}
|
2021-03-09 13:10:22 -05:00
|
|
|
function handleManageNetworkClick(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
props.onManageNetwork();
|
|
|
|
}
|
2020-06-25 12:30:21 -04:00
|
|
|
|
2021-11-29 05:44:28 -05:00
|
|
|
let fullyConnected = props.server.status === ServerStatus.REGISTERED;
|
|
|
|
if (props.bouncerNetwork) {
|
|
|
|
fullyConnected = fullyConnected && props.bouncerNetwork.state === "connected";
|
|
|
|
}
|
|
|
|
|
|
|
|
let description = null, actions = [];
|
2021-05-31 11:30:45 -04:00
|
|
|
switch (props.buffer.type) {
|
|
|
|
case BufferType.SERVER:
|
2021-06-03 05:46:50 -04:00
|
|
|
switch (props.server.status) {
|
|
|
|
case ServerStatus.DISCONNECTED:
|
2021-01-22 05:53:17 -05:00
|
|
|
description = "Disconnected";
|
|
|
|
break;
|
2021-06-03 05:46:50 -04:00
|
|
|
case ServerStatus.CONNECTING:
|
2021-01-22 05:53:17 -05:00
|
|
|
description = "Connecting...";
|
|
|
|
break;
|
2021-06-03 05:46:50 -04:00
|
|
|
case ServerStatus.REGISTERING:
|
2021-01-22 12:29:22 -05:00
|
|
|
description = "Logging in...";
|
|
|
|
break;
|
2021-06-03 05:46:50 -04:00
|
|
|
case ServerStatus.REGISTERED:
|
2021-03-10 05:48:58 -05:00
|
|
|
if (props.bouncerNetwork) {
|
|
|
|
switch (props.bouncerNetwork.state) {
|
|
|
|
case "disconnected":
|
|
|
|
description = "Bouncer disconnected from network";
|
|
|
|
break;
|
|
|
|
case "connecting":
|
|
|
|
description = "Bouncer connecting to network...";
|
|
|
|
break;
|
|
|
|
case "connected":
|
2021-05-27 05:51:29 -04:00
|
|
|
// host can be undefined e.g. when using UNIX domain sockets
|
|
|
|
description = `Connected to ${props.bouncerNetwork.host || "network"}`;
|
2021-03-10 05:48:58 -05:00
|
|
|
break;
|
|
|
|
}
|
2021-05-31 11:30:45 -04:00
|
|
|
} else if (props.buffer.serverInfo) {
|
2021-06-10 12:11:11 -04:00
|
|
|
let serverInfo = props.buffer.serverInfo;
|
2021-03-10 05:48:58 -05:00
|
|
|
description = `Connected to ${serverInfo.name}`;
|
2021-05-31 11:30:45 -04:00
|
|
|
} else {
|
|
|
|
description = "Connected";
|
2021-03-10 05:48:58 -05:00
|
|
|
}
|
2021-01-22 05:53:17 -05:00
|
|
|
break;
|
|
|
|
}
|
2020-06-26 06:45:27 -04:00
|
|
|
|
2021-11-29 05:44:28 -05:00
|
|
|
let joinButton = html`
|
|
|
|
<button
|
|
|
|
key="join"
|
|
|
|
onClick=${handleJoinClick}
|
|
|
|
>Join channel</button>
|
|
|
|
`;
|
|
|
|
|
2021-03-09 13:10:22 -05:00
|
|
|
if (props.isBouncer) {
|
2021-06-03 05:46:50 -04:00
|
|
|
if (props.server.isupport.get("BOUNCER_NETID")) {
|
2021-11-29 05:44:28 -05:00
|
|
|
if (fullyConnected) {
|
|
|
|
actions.push(joinButton);
|
2021-11-30 09:29:24 -05:00
|
|
|
}
|
|
|
|
if (props.server.status === ServerStatus.REGISTERED) {
|
2021-11-29 05:44:28 -05:00
|
|
|
actions.push(html`
|
|
|
|
<button
|
|
|
|
key="manage"
|
|
|
|
onClick=${handleManageNetworkClick}
|
|
|
|
>Manage network</button>
|
|
|
|
`);
|
|
|
|
}
|
2021-03-09 13:10:22 -05:00
|
|
|
} else {
|
2021-11-29 05:44:28 -05:00
|
|
|
if (fullyConnected) {
|
|
|
|
actions.push(html`
|
|
|
|
<button
|
|
|
|
key="add"
|
|
|
|
onClick=${handleAddNetworkClick}
|
|
|
|
>Add network</button>
|
|
|
|
`);
|
|
|
|
}
|
|
|
|
actions.push(html`
|
2021-05-27 13:45:21 -04:00
|
|
|
<button
|
|
|
|
key="disconnect"
|
|
|
|
class="danger"
|
|
|
|
onClick=${handleCloseClick}
|
|
|
|
>Disconnect</button>
|
2021-11-29 05:44:28 -05:00
|
|
|
`);
|
2021-03-09 13:10:22 -05:00
|
|
|
}
|
2021-03-08 12:15:04 -05:00
|
|
|
} else {
|
2021-11-29 05:44:28 -05:00
|
|
|
if (fullyConnected) {
|
|
|
|
actions.push(joinButton);
|
|
|
|
}
|
|
|
|
actions.push(html`
|
2021-05-27 13:45:21 -04:00
|
|
|
<button
|
|
|
|
key="disconnect"
|
|
|
|
class="danger"
|
|
|
|
onClick=${handleCloseClick}
|
|
|
|
>Disconnect</button>
|
2021-11-29 05:44:28 -05:00
|
|
|
`);
|
2021-03-08 12:15:04 -05:00
|
|
|
}
|
2020-06-26 06:00:10 -04:00
|
|
|
break;
|
|
|
|
case BufferType.CHANNEL:
|
2021-05-31 11:30:45 -04:00
|
|
|
if (props.buffer.topic) {
|
2021-05-31 22:39:35 -04:00
|
|
|
description = linkify(stripANSI(props.buffer.topic), props.onChannelClick);
|
2021-05-31 11:30:45 -04:00
|
|
|
}
|
2021-11-05 06:49:56 -04:00
|
|
|
if (props.buffer.joined) {
|
|
|
|
actions = html`
|
|
|
|
<button
|
|
|
|
key="part"
|
|
|
|
class="danger"
|
|
|
|
onClick=${handleCloseClick}
|
|
|
|
>Leave</button>
|
|
|
|
`;
|
|
|
|
} else {
|
2021-11-29 05:44:28 -05:00
|
|
|
if (fullyConnected) {
|
|
|
|
actions.push(html`
|
|
|
|
<button
|
|
|
|
key="join"
|
|
|
|
onClick=${handleJoinClick}
|
|
|
|
>Join</button>
|
|
|
|
`);
|
|
|
|
}
|
2021-11-05 06:49:56 -04:00
|
|
|
actions = html`
|
|
|
|
<button
|
|
|
|
key="part"
|
|
|
|
class="danger"
|
|
|
|
onClick=${handleCloseClick}
|
|
|
|
>Close</button>
|
|
|
|
`;
|
|
|
|
}
|
2021-03-09 13:10:22 -05:00
|
|
|
break;
|
|
|
|
case BufferType.NICK:
|
2021-09-21 07:33:15 -04:00
|
|
|
if (props.user) {
|
2021-06-10 12:11:11 -04:00
|
|
|
let status = UserStatus.HERE;
|
2021-09-21 07:33:15 -04:00
|
|
|
if (props.user.offline) {
|
|
|
|
status = UserStatus.OFFLINE;
|
|
|
|
} else if (props.user.away) {
|
2021-05-31 11:30:45 -04:00
|
|
|
status = UserStatus.GONE;
|
|
|
|
}
|
2021-09-21 07:33:15 -04:00
|
|
|
|
|
|
|
let realname = props.buffer.name;
|
2021-09-21 11:24:39 -04:00
|
|
|
if (irc.isMeaningfulRealname(props.user.realname, props.buffer.name)) {
|
2021-09-21 07:33:15 -04:00
|
|
|
realname = stripANSI(props.user.realname || "");
|
|
|
|
}
|
|
|
|
|
2021-09-21 09:38:59 -04:00
|
|
|
let details = [];
|
2021-09-21 07:33:15 -04:00
|
|
|
if (props.user.username && props.user.hostname) {
|
2021-09-21 09:38:59 -04:00
|
|
|
details.push(`${props.user.username}@${props.user.hostname}`);
|
2021-05-31 11:30:45 -04:00
|
|
|
}
|
2021-09-21 09:38:59 -04:00
|
|
|
if (props.user.account) {
|
2021-11-03 12:23:32 -04:00
|
|
|
let desc = `This user is verified and has logged in to the server with the account ${props.user.account}.`;
|
|
|
|
let item;
|
2021-11-02 13:01:07 -04:00
|
|
|
if (props.user.account === props.buffer.name) {
|
2021-11-03 12:23:32 -04:00
|
|
|
item = "authenticated";
|
2021-11-02 13:01:07 -04:00
|
|
|
} else {
|
2021-11-03 12:23:32 -04:00
|
|
|
item = `authenticated as ${props.user.account}`;
|
2021-11-02 13:01:07 -04:00
|
|
|
}
|
2021-11-03 12:23:32 -04:00
|
|
|
details.push(html`<abbr title=${desc}>${item}</abbr>`);
|
2021-11-02 13:04:21 -04:00
|
|
|
} else if (props.server.isupport.has("MONITOR") && props.server.isupport.has("WHOX")) {
|
|
|
|
// If the server supports MONITOR and WHOX, we can faithfully
|
|
|
|
// keep user.account up-to-date for user queries
|
2021-11-03 12:23:32 -04:00
|
|
|
let desc = "This user has not been verified and is not logged in.";
|
|
|
|
details.push(html`<abbr title=${desc}>unauthenticated</abbr>`);
|
2021-09-21 09:38:59 -04:00
|
|
|
}
|
2021-11-01 13:45:16 -04:00
|
|
|
if (props.user.operator) {
|
2021-11-03 12:23:32 -04:00
|
|
|
let desc = "This user is a server operator, they have administrator privileges.";
|
|
|
|
details.push(html`<abbr title=${desc}>server operator</abbr>`);
|
|
|
|
}
|
|
|
|
details = details.map((item, i) => {
|
|
|
|
if (i === 0) {
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
return [", ", item];
|
|
|
|
});
|
|
|
|
if (details.length > 0) {
|
|
|
|
details = ["(", details, ")"];
|
2021-11-01 13:45:16 -04:00
|
|
|
}
|
2021-05-31 11:30:45 -04:00
|
|
|
|
2021-09-21 09:38:59 -04:00
|
|
|
description = html`<${NickStatus} status=${status}/> ${realname} ${details}`;
|
2021-05-31 11:30:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
actions = html`
|
|
|
|
<button
|
|
|
|
key="close"
|
|
|
|
class="danger"
|
|
|
|
onClick=${handleCloseClick}
|
|
|
|
>Close</button>
|
|
|
|
`;
|
2020-06-26 06:00:10 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-06-10 12:11:11 -04:00
|
|
|
let name = props.buffer.name;
|
2021-05-31 11:39:37 -04:00
|
|
|
if (props.buffer.type == BufferType.SERVER) {
|
2021-06-03 07:10:44 -04:00
|
|
|
name = getServerName(props.server, props.bouncerNetwork, props.isBouncer);
|
2021-05-31 11:39:37 -04:00
|
|
|
}
|
|
|
|
|
2020-06-25 12:30:21 -04:00
|
|
|
return html`
|
2021-06-06 11:27:05 -04:00
|
|
|
<div class="title">${name}</div>
|
|
|
|
${description ? html`<div class="description">${description}</div>` : null}
|
|
|
|
<div class="actions">${actions}</div>
|
2020-06-25 12:30:21 -04:00
|
|
|
`;
|
|
|
|
}
|