Skip to content

Commit 6636f2b

Browse files
authored
feat: add chat peer list (#147)
fixes #21 Co-authored-by: Daniel N <[email protected]>
1 parent ba9c27c commit 6636f2b

File tree

7 files changed

+83
-134
lines changed

7 files changed

+83
-134
lines changed

js-peer/blockies.d.ts

-1
This file was deleted.

js-peer/package-lock.json

+9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

js-peer/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
"@chainsafe/libp2p-gossipsub": "^13.0.0",
1111
"@chainsafe/libp2p-noise": "^15.0.0",
1212
"@chainsafe/libp2p-yamux": "^6.0.2",
13-
"@download/blockies": "^1.0.3",
1413
"@headlessui/react": "^2.0.1",
1514
"@helia/delegated-routing-v1-http-api-client": "^3.0.1",
1615
"@heroicons/react": "^2.1.3",
@@ -32,6 +31,7 @@
3231
"libp2p": "^1.5.1",
3332
"next": "14.2.2",
3433
"react": "18.2.0",
34+
"react-18-blockies": "^1.0.6",
3535
"react-dom": "18.2.0",
3636
"uint8arrays": "^5.0.3",
3737
"usehooks-ts": "^3.1.0",
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { useLibp2pContext } from '@/context/ctx'
2+
import { CHAT_TOPIC } from '@/lib/constants'
3+
import React, { useEffect, useState } from 'react'
4+
import type { PeerId } from '@libp2p/interface'
5+
import Blockies from 'react-18-blockies'
6+
7+
export function ChatPeerList() {
8+
const { libp2p } = useLibp2pContext()
9+
const [subscribers, setSubscribers] = useState<PeerId[]>([])
10+
11+
useEffect(() => {
12+
const onSubscriptionChange = () => {
13+
const subscribers = libp2p.services.pubsub.getSubscribers(CHAT_TOPIC)
14+
setSubscribers(subscribers)
15+
}
16+
onSubscriptionChange()
17+
libp2p.services.pubsub.addEventListener('subscription-change', onSubscriptionChange)
18+
return () => {
19+
libp2p.services.pubsub.removeEventListener('subscription-change', onSubscriptionChange)
20+
}
21+
}, [libp2p, setSubscribers])
22+
23+
return (
24+
<div className="border-l border-gray-300 lg:col-span-1">
25+
<h2 className="my-2 mb-2 ml-2 text-lg text-gray-600">Peers</h2>
26+
<ul className="overflow-auto h-[32rem]">
27+
{<Peer key={libp2p.peerId.toString()} peer={libp2p.peerId} self />}
28+
{subscribers.map((p) => (
29+
<Peer key={p.toString()} peer={p} self={false} />
30+
))}
31+
</ul>
32+
</div>
33+
)
34+
}
35+
36+
function Peer({ peer, self }: { peer: PeerId; self: boolean }) {
37+
return (
38+
<li className="flex items-center px-3 py-2 text-sm transition duration-150 ease-in-out border-b border-gray-300 focus:outline-none">
39+
<Blockies seed={peer.toString()} size={15} scale={3} className="rounded max-h-10 max-w-10" />
40+
<div className="w-full pb-2">
41+
<div className="flex justify-between">
42+
<span className={`block ml-2 font-semibold ${self ? 'text-indigo-700-600' : 'text-gray-600'}`}>
43+
{peer.toString().slice(-7)}
44+
{self && ' (You)'}
45+
</span>
46+
</div>
47+
</div>
48+
</li>
49+
)
50+
}

js-peer/src/components/chat.tsx

+5-12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ChatFile, ChatMessage, useChatContext } from '../context/chat-ctx'
55
import { v4 as uuidv4 } from 'uuid'
66
import { MessageComponent } from './message'
77
import { forComponent } from '@/lib/logger'
8+
import { ChatPeerList } from './chat-peer-list'
89

910
const log = forComponent('chat')
1011

@@ -121,22 +122,13 @@ export default function ChatContainer() {
121122

122123
return (
123124
<div className="container mx-auto">
124-
<div className="min-w-full border rounded lg:grid lg:grid-cols-3">
125-
{/* <RoomList /> */}
126-
<div className="lg:col-span-3 lg:block">
125+
<div className="min-w-full border rounded lg:grid lg:grid-cols-6">
126+
<div className="lg:col-span-5 lg:block">
127127
<div className="w-full">
128128
<div className="relative flex items-center p-3 border-b border-gray-300">
129-
{/* disable
130-
<img
131-
className="object-cover w-10 h-10 rounded-full"
132-
src="https://github.com/achingbrain.png"
133-
alt="username"
134-
/>
135-
<span className="absolute w-3 h-3 bg-green-600 rounded-full left-10 top-3"></span> */}
136-
<span className="text-3xl">💁🏽‍♀️💁🏿‍♂️</span>
137129
<span className="block ml-2 font-bold text-gray-600">Public Chat</span>
138130
</div>
139-
<div className="relative w-full flex flex-col-reverse p-6 overflow-y-auto h-[40rem] bg-gray-100">
131+
<div className="relative w-full flex flex-col-reverse p-3 overflow-y-auto h-[40rem] bg-gray-100">
140132
<ul className="space-y-2">
141133
{/* messages start */}
142134
{messageHistory.map(({ msg, fileObjectUrl, from, peerId }, idx) => (
@@ -194,6 +186,7 @@ export default function ChatContainer() {
194186
</div>
195187
</div>
196188
</div>
189+
<ChatPeerList />
197190
</div>
198191
</div>
199192
)

js-peer/src/components/message.tsx

+18-28
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,33 @@
11
import { useLibp2pContext } from '@/context/ctx'
22
import React, { useCallback, useEffect, useRef, useState } from 'react'
3-
import { createIcon } from '@download/blockies'
43
import { ChatMessage } from '@/context/chat-ctx'
4+
import Blockies from 'react-18-blockies'
55

6-
7-
interface MessageProps extends ChatMessage { }
8-
6+
interface MessageProps extends ChatMessage {}
97

108
export function MessageComponent({ msg, fileObjectUrl, from, peerId }: MessageProps) {
11-
const msgref = React.useRef<HTMLLIElement>(null)
129
const { libp2p } = useLibp2pContext()
1310

14-
15-
useEffect(() => {
16-
const icon = createIcon({
17-
seed: peerId,
18-
size: 15,
19-
scale: 3,
20-
})
21-
icon.className = 'rounded mr-2 max-h-10 max-w-10'
22-
const childrenCount = msgref.current?.childElementCount
23-
// Prevent inserting an icon more than once.
24-
if (childrenCount && childrenCount < 2) {
25-
msgref.current?.insertBefore(icon, msgref.current?.firstChild)
26-
}
27-
}, [peerId])
28-
2911
return (
30-
<li ref={msgref} className={`flex ${from === 'me' ? 'justify-end' : 'justify-start'}`}>
31-
<div
32-
33-
className="flex relative max-w-xl px-4 py-2 text-gray-700 rounded shadow bg-white"
34-
>
12+
<li className={`flex ${from === 'me' && 'flex-row-reverse'} gap-2`}>
13+
<Blockies seed={peerId} size={15} scale={3} className="rounded max-h-10 max-w-10" />
14+
<div className="flex relative max-w-xl px-4 py-2 text-gray-700 rounded shadow bg-white">
3515
<div className="block">
3616
{msg}
37-
<p>{fileObjectUrl ? <a href={fileObjectUrl} target="_blank"><b>Download</b></a> : ""}</p>
38-
<p className="italic text-gray-400">{peerId !== libp2p.peerId.toString() ? `from: ${peerId.slice(-4)}` : null} </p>
17+
<p>
18+
{fileObjectUrl ? (
19+
<a href={fileObjectUrl} target="_blank">
20+
<b>Download</b>
21+
</a>
22+
) : (
23+
''
24+
)}
25+
</p>
26+
<p className="italic text-gray-400">
27+
{peerId !== libp2p.peerId.toString() ? `from: ${peerId.slice(-4)}` : null}{' '}
28+
</p>
3929
</div>
4030
</div>
4131
</li>
4232
)
43-
}
33+
}

js-peer/src/components/room-list.tsx

-92
This file was deleted.

0 commit comments

Comments
 (0)