Files
waste-go/web/src/components/PeerList.tsx
Fredrik Johansson ff14e955ea feat: standalone web UI (React + Vite)
React + TypeScript UI on port 5274. Connects to local daemon via
WebSocket IPC (DaemonAdapter). Full chat layout with sidebar, message
pane, and peer list. Mirrors the TUI feature set.

- src/types.ts        — IPC types mirroring proto.go
- src/adapter/daemon  — WebSocket IPC adapter with auto-reconnect
- src/store/index.ts  — Zustand store; handles all daemon events
- src/pages/          — Onboarding (connect + join) and Chat
- src/components/     — Sidebar, MessagePane, PeerList

Dev: cd web && npm run dev  (port 5274)
Build: cd web && npm run build

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-22 21:57:32 +02:00

36 lines
1.1 KiB
TypeScript

import { useWaste } from '../store'
export function PeerList() {
const { connectedPeers, activeNetworkId, setActiveRoom, send } = useWaste()
function openDM(peerId: string) {
const room = `dm:${peerId}`
setActiveRoom(room)
}
function requestFiles(peerId: string) {
send({ type: 'get_file_list', network_id: activeNetworkId ?? undefined, peer_id: peerId })
}
return (
<aside className="peer-list">
<span className="sidebar-label">Peers ({connectedPeers.length})</span>
{connectedPeers.map(p => (
<div key={p.id} className="peer-entry">
<div className="peer-entry-info">
<span className="alias">{p.alias}</span>
<span className="peer-id">{p.id.slice(0, 8)}</span>
</div>
<div className="peer-entry-actions">
<button onClick={() => openDM(p.id)} title="Direct message">DM</button>
<button onClick={() => requestFiles(p.id)} title="Browse files">Files</button>
</div>
</div>
))}
{connectedPeers.length === 0 && (
<p className="empty">No peers connected yet</p>
)}
</aside>
)
}