Skip to content

Commit 3648ed3

Browse files
committed
Display live usenet connection count in UI (#34)
1 parent 12be368 commit 3648ed3

File tree

4 files changed

+90
-0
lines changed

4 files changed

+90
-0
lines changed

frontend/app/routes/_index/components/left-navigation/left-navigation.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Form, Link, useLocation, useNavigation } from "react-router";
22
import styles from "./left-navigation.module.css";
33
import { className } from "~/utils/styling";
44
import type React from "react";
5+
import { LiveUsenetConnections } from "../live-usenet-connections/live-usenet-connections";
56

67
export function LeftNavigation() {
78
return (
@@ -18,6 +19,7 @@ export function LeftNavigation() {
1819
<div className={styles["settings-icon"]} />
1920
<div className={styles.title}>Settings</div>
2021
</Item>
22+
<LiveUsenetConnections />
2123

2224
<div className={styles.footer}>
2325
<div className={styles["footer-item"]}>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
.container {
2+
width: 100%;
3+
margin-top: 25px;
4+
}
5+
6+
.title {
7+
font-size: 14px;
8+
margin-bottom: 5px;
9+
}
10+
11+
.max {
12+
background-color: #93a1a1;
13+
position: relative;
14+
border-radius: 10px;
15+
height: 10px;
16+
overflow: hidden;
17+
}
18+
19+
.live {
20+
background-color: #eee8d5;
21+
position: absolute;
22+
height: 100%;
23+
width: 0%;
24+
}
25+
26+
.active {
27+
background-color: #268bd2;
28+
position: absolute;
29+
height: 100%;
30+
width: 0%;
31+
}
32+
33+
.caption {
34+
text-align: right;
35+
margin-right: 5px;
36+
font-size: 12px;
37+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
declare const styles: {
2+
readonly "container": string;
3+
readonly "title": string;
4+
readonly "max": string;
5+
readonly "live": string;
6+
readonly "active": string;
7+
readonly "caption": string;
8+
};
9+
export = styles;
10+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { useEffect, useState } from "react";
2+
import styles from "./live-usenet-connections.module.css";
3+
4+
const usenetConnectionsTopic = "cxs";
5+
6+
export function LiveUsenetConnections() {
7+
const [connections, setConnections] = useState<string | null>(null);
8+
const parts = (connections || "0|1|0").split("|");
9+
const [live, max, idle] = parts.map(x => Number(x));
10+
const active = live - idle;
11+
const activePercent = 100 * (active / max);
12+
const livePercent = 100 * (live / max);
13+
14+
useEffect(() => {
15+
const ws = new WebSocket(window.location.origin.replace(/^http/, 'ws'));
16+
ws.onmessage = (event) => setConnections(event.data);
17+
ws.onopen = () => ws.send(usenetConnectionsTopic);
18+
return () => ws.close();
19+
}, [setConnections]);
20+
21+
return (
22+
<div className={styles.container}>
23+
<div className={styles.title}>
24+
Usenet Connections
25+
</div>
26+
<div className={styles.max}>
27+
<div className={styles.live} style={{ width: `${livePercent}%` }} />
28+
<div className={styles.active} style={{ width: `${activePercent}%` }} />
29+
</div>
30+
<div className={styles.caption}>
31+
{connections && `${live} connected / ${max} max`}
32+
{!connections && `Loading...`}
33+
</div>
34+
{connections &&
35+
<div className={styles.caption}>
36+
( {active} active )
37+
</div>
38+
}
39+
</div>
40+
);
41+
}

0 commit comments

Comments
 (0)