11import React , { useEffect , useMemo , useRef , useState } from 'react'
22import { Peer } from 'peerjs'
3+ import StatusSelector from "../components/StatusSelector" ;
4+
35
46// Simple in-memory presence for same-tab demo. For multi-user on same Wi-Fi without a server,
57// users need to share their Peer IDs manually or via a QR/text. We add a QR helper below.
@@ -27,6 +29,8 @@ const defaultConfig = {
2729 path : '/' // default path for public broker
2830}
2931
32+
33+
3034function copy ( text ) {
3135 navigator . clipboard ?. writeText ( text ) . catch ( ( ) => { } )
3236}
@@ -46,7 +50,11 @@ export default function App() {
4650 const [ cfg , setCfg ] = useLocalStorage ( 'peer.cfg' , defaultConfig )
4751 const [ label , setLabel ] = useLocalStorage ( 'peer.label' , '' )
4852 const [ recentRooms , setRecentRooms ] = useLocalStorage ( 'peer.recentRooms' , [ ] )
49- const [ status , setStatus ] = useState ( 'idle' )
53+ // replacing const [status, setStatus] = useState('idle')
54+
55+ const [ status , setStatus ] = useState ( localStorage . getItem ( "peer.status" ) || 'idle' ) ;
56+ //Add a peerStatuses state object:
57+ const [ peerStatuses , setPeerStatuses ] = useState ( { } ) ;
5058 const [ myId , setMyId ] = useState ( '' )
5159 const [ peerIdInput , setPeerIdInput ] = useState ( '' )
5260 const [ roomCode , setRoomCode ] = useState ( '' )
@@ -61,11 +69,23 @@ export default function App() {
6169 const [ showRecentRooms , setShowRecentRooms ] = useState ( false )
6270
6371 const peerRef = useRef ( null )
64- const connRef = useRef ( null )
72+ const connRef = useRef ( { } )
6573 const mediaRef = useRef ( null )
6674 const audioRef = useRef ( null )
6775 const chatEndRef = useRef ( null )
6876
77+
78+ //adding function for better optimization
79+ function getStatusColor ( status ) {
80+ switch ( status ) {
81+ case 'online' : return '#10b981' ;
82+ case 'away' : return '#f59e0b' ;
83+ case 'busy' : return '#ef4444' ;
84+ case 'offline' :return '#6b7280' ;
85+ default : return '#10b981' ;
86+ }
87+ }
88+
6989 const peerOptions = useMemo ( ( ) => ( {
7090 host : cfg . host , port : Number ( cfg . port ) , secure : ! ! cfg . secure , path : cfg . path || '/' ,
7191 config : {
@@ -145,21 +165,49 @@ export default function App() {
145165 setConnected ( true )
146166 pushLog ( 'Connected to ' + conn . peer )
147167
148- conn . on ( 'data' , ( data ) => {
149- if ( data ?. type === 'presence' ) {
150- setPeers ( ( p ) => mergePeers ( p , data . payload ) )
151- } else if ( data ?. type === 'message' ) {
152- setMessages ( ( msgs ) => [ ...msgs , {
168+ conn . on ( 'data' , ( data ) => {
169+ if ( ! data ) return ;
170+
171+ switch ( data . type ) {
172+ case 'presence' :
173+ // Merge presence info into peers list
174+ setPeers ( ( prevPeers ) => mergePeers ( prevPeers , data . payload ) ) ;
175+ break ;
176+
177+ case 'message' :
178+ // Append incoming chat message
179+ setMessages ( ( msgs ) => [
180+ ...msgs ,
181+ {
153182 text : data . text ,
154183 sender : data . sender ,
155184 timestamp : data . timestamp ,
156- isMe : false
157- } ] )
158- pushLog ( `Message from ${ data . sender } : ${ data . text } ` )
159- } else if ( data ?. type === 'signal' ) {
160- // Place for extra messages if needed
161- }
162- } )
185+ isMe : false ,
186+ } ,
187+ ] ) ;
188+ pushLog ( `Message from ${ data . sender } : ${ data . text } ` ) ;
189+ break ;
190+
191+ case 'status-update' :
192+ // Update peerStatuses map with latest status
193+ setPeerStatuses ( ( prev ) => ( {
194+ ...prev ,
195+ [ conn . peer ] : data . status ,
196+ } ) ) ;
197+ pushLog ( `Status update from ${ conn . peer } : ${ data . status } ` ) ;
198+ break ;
199+
200+ case 'signal' :
201+ // Reserved for future signals
202+ break ;
203+
204+ default :
205+ console . warn ( 'Unknown data type received:' , data ) ;
206+ break ;
207+ }
208+ } ) ;
209+
210+
163211
164212 conn . on ( 'close' , ( ) => {
165213 setConnected ( false )
@@ -301,6 +349,7 @@ export default function App() {
301349 const qrUrl = myId ? generateQR ( shareableUrl ) : ''
302350
303351 return (
352+
304353 < div className = "app" >
305354 < style > { `
306355 .app {
@@ -505,6 +554,30 @@ export default function App() {
505554 }
506555 ` } </ style >
507556
557+ { /* availability Status Section */ }
558+ < div className = "card" style = { { marginTop : 16 , padding : 16 } } >
559+ < div className = "small" style = { { marginBottom : 8 } } > Your Availability</ div >
560+ < StatusSelector
561+ status = { status }
562+ onChange = { ( newStatus ) => {
563+ setStatus ( newStatus ) ;
564+ localStorage . setItem ( "peer.status" , newStatus ) ;
565+
566+ // Broadcast to all connected peers
567+ peers . forEach ( ( p ) => {
568+ const conn = connRef . current [ p . id ] ;
569+ if ( conn && conn . open ) {
570+ conn . send ( { type : "status-update" , status : newStatus } ) ;
571+ }
572+ } ) ;
573+ } }
574+ />
575+
576+ </ div >
577+
578+
579+
580+
508581 < div className = "card" >
509582 < div className = "header" >
510583 < h2 className = "h" > Local P2P Voice Chat</ h2 >
@@ -675,36 +748,53 @@ export default function App() {
675748 </ div >
676749
677750 { /* Presence Display Section */ }
678- < div className = "card" style = { { marginTop : 16 , padding : 16 } } >
679- < div className = "small" style = { { marginBottom : 8 } } > Connected Peers</ div >
680- { peers . length === 0 ? (
681- < div className = "small" style = { { opacity : 0.5 , textAlign : 'center' , padding : '20px' } } >
682- No peers connected. Share your Peer ID or room code to connect with others.
683- </ div >
684- ) : (
685- < div className = "list" >
686- { peers . map ( ( peer , i ) => (
687- < div key = { i } className = "peer" >
688- < div >
689- < div style = { { fontWeight : '500' } } >
690- { peer . label || 'Anonymous' }
691- { peer . roomCode && < span className = "badge small" style = { { marginLeft : '8px' } } > Room: { peer . roomCode } </ span > }
692- </ div >
693- < div className = "small" style = { { fontFamily : 'monospace' } } >
694- { peer . id }
695- </ div >
696- < div className = "small" style = { { opacity : 0.7 } } >
697- Last seen: { new Date ( peer . ts ) . toLocaleTimeString ( ) }
698- </ div >
699- </ div >
700- < div className = "badge small" style = { { backgroundColor : '#10b981' } } >
701- Online
702- </ div >
703- </ div >
704- ) ) }
705- </ div >
706- ) }
707- </ div >
751+ < div className = "card" style = { { marginTop : 16 , padding : 16 } } >
752+ < div className = "small" style = { { marginBottom : 8 } } > Connected Peers</ div >
753+ { peers . length === 0 ? (
754+ < div className = "small" style = { { opacity : 0.5 , textAlign : 'center' , padding : '20px' } } >
755+ No peers connected. Share your Peer ID or room code to connect with others.
756+ </ div >
757+ ) : (
758+ < div className = "list" >
759+ { peers . map ( ( peer , i ) => (
760+ < div key = { i } className = "peer" style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' , marginBottom : 8 } } >
761+ < div >
762+ < div style = { { fontWeight : 500 } } >
763+ { peer . label || 'Anonymous' }
764+ { peer . roomCode && (
765+ < span className = "badge small" style = { { marginLeft : '8px' , backgroundColor : '#3b82f6' } } >
766+ Room: { peer . roomCode }
767+ </ span >
768+ ) }
769+ </ div >
770+ < div className = "small" style = { { fontFamily : 'monospace' } } >
771+ { peer . id }
772+ </ div >
773+ < div className = "small" style = { { opacity : 0.7 } } >
774+ Last seen: { new Date ( peer . ts ) . toLocaleTimeString ( ) }
775+ </ div >
776+ </ div >
777+
778+ { /* Dynamic Status Badge */ }
779+ < div
780+ className = "badge small"
781+ style = { {
782+ backgroundColor : getStatusColor ( peerStatuses [ peer . id ] ) ,
783+ color : 'white' ,
784+ padding : '2px 8px' ,
785+ borderRadius : '6px' ,
786+ fontWeight : 500 ,
787+ } }
788+ >
789+ { peerStatuses [ peer . id ] ?. toUpperCase ( ) || 'ONLINE' }
790+ </ div >
791+
792+ </ div >
793+ ) ) }
794+ </ div >
795+ ) }
796+ </ div >
797+
708798
709799 < div className = "card" style = { { marginTop : 16 , padding : 16 } } >
710800 < div className = "small" style = { { marginBottom : 8 } } > Log</ div >
0 commit comments