1- import React from " react" ;
2- import { MdCheckCircle , MdCloudOff , MdCloudQueue , MdErrorOutline , MdSync } from " react-icons/md" ;
1+ import React from ' react' ;
2+ import { MdCheckCircle , MdCloudOff , MdCloudQueue , MdErrorOutline , MdSync } from ' react-icons/md' ;
33
4- import { PLAYGROUND_PUBLIC_DISCOVERY_URL } from " ../constants" ;
5- import type { PeerInfo , RemoteSyncStatus , SyncTransportMode } from " ../types" ;
4+ import { PLAYGROUND_PUBLIC_DISCOVERY_URL } from ' ../constants' ;
5+ import type { PeerInfo , RemoteSyncStatus , SyncTransportMode } from ' ../types' ;
66
77function formatPeerId ( id : string ) : string {
8- if ( id . startsWith ( " remote:" ) ) return `remote(${ id . slice ( " remote:" . length ) } )` ;
8+ if ( id . startsWith ( ' remote:' ) ) return `remote(${ id . slice ( ' remote:' . length ) } )` ;
99 return id . length > 18 ? `${ id . slice ( 0 , 8 ) } …${ id . slice ( - 6 ) } ` : id ;
1010}
1111
1212function transportModeButtonClass ( active : boolean ) : string {
1313 return active
14- ? " border-accent bg-accent/15 text-white"
15- : " border-slate-700 bg-slate-900/70 text-slate-300 hover:border-slate-500 hover:text-white" ;
14+ ? ' border-accent bg-accent/15 text-white'
15+ : ' border-slate-700 bg-slate-900/70 text-slate-300 hover:border-slate-500 hover:text-white' ;
1616}
1717
1818function remoteStatusTone ( status : RemoteSyncStatus ) : string {
1919 switch ( status . state ) {
20- case " connected" :
21- return " border-emerald-500/40 bg-emerald-500/10 text-emerald-100" ;
22- case " connecting" :
23- return " border-sky-500/40 bg-sky-500/10 text-sky-100" ;
24- case " disabled" :
25- return " border-slate-700 bg-slate-900/70 text-slate-400" ;
26- case " missing_url" :
27- return " border-amber-500/30 bg-amber-500/10 text-amber-100" ;
28- case " invalid" :
29- case " error" :
30- return " border-rose-500/40 bg-rose-500/10 text-rose-100" ;
20+ case ' connected' :
21+ return ' border-emerald-500/40 bg-emerald-500/10 text-emerald-100' ;
22+ case ' connecting' :
23+ return ' border-sky-500/40 bg-sky-500/10 text-sky-100' ;
24+ case ' disabled' :
25+ return ' border-slate-700 bg-slate-900/70 text-slate-400' ;
26+ case ' missing_url' :
27+ return ' border-amber-500/30 bg-amber-500/10 text-amber-100' ;
28+ case ' invalid' :
29+ case ' error' :
30+ return ' border-rose-500/40 bg-rose-500/10 text-rose-100' ;
3131 }
3232}
3333
3434function RemoteStatusIcon ( { status } : { status : RemoteSyncStatus } ) {
35- if ( status . state === " connected" ) {
35+ if ( status . state === ' connected' ) {
3636 return < MdCheckCircle className = "text-[14px]" /> ;
3737 }
38- if ( status . state === " connecting" ) {
38+ if ( status . state === ' connecting' ) {
3939 return < MdSync className = "text-[14px]" /> ;
4040 }
41- if ( status . state === " disabled" ) {
41+ if ( status . state === ' disabled' ) {
4242 return < MdCloudOff className = "text-[14px]" /> ;
4343 }
4444 return < MdErrorOutline className = "text-[14px]" /> ;
@@ -63,7 +63,7 @@ export function PeersPanel({
6363 remoteSyncStatus : RemoteSyncStatus ;
6464 peers : PeerInfo [ ] ;
6565} ) {
66- const requiresRemoteUrl = syncTransportMode !== " local" ;
66+ const requiresRemoteUrl = syncTransportMode !== ' local' ;
6767 const hasRemoteUrl = syncServerUrl . trim ( ) . length > 0 ;
6868
6969 return (
@@ -73,74 +73,86 @@ export function PeersPanel({
7373 >
7474 < div className = "flex flex-wrap items-start justify-between gap-3" >
7575 < div >
76- < div className = "text-[10px] font-semibold uppercase tracking-wide text-slate-400" > Connections</ div >
76+ < div className = "text-[10px] font-semibold uppercase tracking-wide text-slate-400" >
77+ Connections
78+ </ div >
7779 < div className = "mt-1 max-w-xl text-[11px] text-slate-400" >
78- Choose how this tab syncs. Local tabs use `BroadcastChannel`. Remote transport can use either a direct
79- websocket sync endpoint or an HTTP bootstrap endpoint.
80+ Choose how this tab syncs. Local tabs use `BroadcastChannel`. Remote transport can use
81+ either a direct websocket sync endpoint or a separate HTTP bootstrap endpoint.
8082 </ div >
8183 </ div >
8284 < button
8385 className = { `flex h-8 items-center gap-2 rounded-lg border px-3 text-[11px] font-semibold transition ${
8486 online
85- ? " border-slate-700 bg-slate-800/70 text-slate-200 hover:border-accent hover:text-white"
86- : " border-amber-500/60 bg-amber-500/10 text-amber-100 hover:border-amber-400"
87+ ? ' border-slate-700 bg-slate-800/70 text-slate-200 hover:border-accent hover:text-white'
88+ : ' border-amber-500/60 bg-amber-500/10 text-amber-100 hover:border-amber-400'
8789 } `}
8890 onClick = { ( ) => setOnline ( ( v ) => ! v ) }
8991 type = "button"
90- title = { online ? " Pause sync activity" : " Resume sync activity" }
92+ title = { online ? ' Pause sync activity' : ' Resume sync activity' }
9193 >
92- { online ? < MdCloudQueue className = "text-[16px]" /> : < MdCloudOff className = "text-[16px]" /> }
93- < span > { online ? "Sync enabled" : "Sync paused" } </ span >
94+ { online ? (
95+ < MdCloudQueue className = "text-[16px]" />
96+ ) : (
97+ < MdCloudOff className = "text-[16px]" />
98+ ) }
99+ < span > { online ? 'Sync enabled' : 'Sync paused' } </ span >
94100 </ button >
95101 </ div >
96102
97103 < div className = "mt-3 rounded-lg border border-slate-800/70 bg-slate-950/30 p-2" >
98- < div className = "text-[10px] font-semibold uppercase tracking-wide text-slate-400" > Transport</ div >
104+ < div className = "text-[10px] font-semibold uppercase tracking-wide text-slate-400" >
105+ Transport
106+ </ div >
99107 < div className = "mt-2 flex flex-wrap gap-2" >
100108 < button
101109 type = "button"
102- className = { `rounded-md border px-3 py-1.5 text-[11px] font-semibold transition ${ transportModeButtonClass ( syncTransportMode === " local" ) } ` }
103- onClick = { ( ) => setSyncTransportMode ( " local" ) }
110+ className = { `rounded-md border px-3 py-1.5 text-[11px] font-semibold transition ${ transportModeButtonClass ( syncTransportMode === ' local' ) } ` }
111+ onClick = { ( ) => setSyncTransportMode ( ' local' ) }
104112 >
105113 Local tabs
106114 </ button >
107115 < button
108116 type = "button"
109- className = { `rounded-md border px-3 py-1.5 text-[11px] font-semibold transition ${ transportModeButtonClass ( syncTransportMode === " remote" ) } ` }
110- onClick = { ( ) => setSyncTransportMode ( " remote" ) }
117+ className = { `rounded-md border px-3 py-1.5 text-[11px] font-semibold transition ${ transportModeButtonClass ( syncTransportMode === ' remote' ) } ` }
118+ onClick = { ( ) => setSyncTransportMode ( ' remote' ) }
111119 >
112120 Remote server
113121 </ button >
114122 < button
115123 type = "button"
116- className = { `rounded-md border px-3 py-1.5 text-[11px] font-semibold transition ${ transportModeButtonClass ( syncTransportMode === " hybrid" ) } ` }
117- onClick = { ( ) => setSyncTransportMode ( " hybrid" ) }
124+ className = { `rounded-md border px-3 py-1.5 text-[11px] font-semibold transition ${ transportModeButtonClass ( syncTransportMode === ' hybrid' ) } ` }
125+ onClick = { ( ) => setSyncTransportMode ( ' hybrid' ) }
118126 >
119127 Hybrid
120128 </ button >
121129 </ div >
122130 < div className = "mt-2 text-[11px] text-slate-500" >
123- { syncTransportMode === "local" && "Only same-origin tabs in this browser will sync." }
124- { syncTransportMode === "remote" && "Only the configured websocket sync server will be used." }
125- { syncTransportMode === "hybrid" && "Use both same-origin tabs and the configured websocket sync server." }
131+ { syncTransportMode === 'local' && 'Only same-origin tabs in this browser will sync.' }
132+ { syncTransportMode === 'remote' &&
133+ 'Only the configured remote websocket or bootstrap endpoint will be used.' }
134+ { syncTransportMode === 'hybrid' &&
135+ 'Use both same-origin tabs and the configured remote websocket or bootstrap endpoint.' }
126136 </ div >
127137 </ div >
128138
129139 < div className = "mt-3 rounded-lg border border-slate-800/70 bg-slate-950/30 p-2" >
130140 < div className = "flex items-center justify-between gap-2" >
131- < div className = "text-[10px] font-semibold uppercase tracking-wide text-slate-400" > Remote sync server</ div >
141+ < div className = "text-[10px] font-semibold uppercase tracking-wide text-slate-400" >
142+ Remote sync / bootstrap
143+ </ div >
132144 < div
133145 className = { `inline-flex items-center gap-1.5 rounded-full border px-2 py-1 text-[10px] font-semibold ${ remoteStatusTone ( remoteSyncStatus ) } ` }
134146 title = { remoteSyncStatus . detail }
135147 >
136148 < RemoteStatusIcon status = { remoteSyncStatus } />
137149 < span >
138- { remoteSyncStatus . state === " connected" && " Connected" }
139- { remoteSyncStatus . state === " connecting" && " Connecting" }
140- { remoteSyncStatus . state === " disabled" && " Inactive" }
141- { remoteSyncStatus . state === " missing_url" && " Missing URL" }
142- { remoteSyncStatus . state === " invalid" && " Invalid URL" }
143- { remoteSyncStatus . state === " error" && " Unreachable" }
150+ { remoteSyncStatus . state === ' connected' && ' Connected' }
151+ { remoteSyncStatus . state === ' connecting' && ' Connecting' }
152+ { remoteSyncStatus . state === ' disabled' && ' Inactive' }
153+ { remoteSyncStatus . state === ' missing_url' && ' Missing URL' }
154+ { remoteSyncStatus . state === ' invalid' && ' Invalid URL' }
155+ { remoteSyncStatus . state === ' error' && ' Unreachable' }
144156 </ span >
145157 </ div >
146158 </ div >
@@ -151,20 +163,20 @@ export function PeersPanel({
151163 onChange = { ( event ) => {
152164 const next = event . target . value ;
153165 setSyncServerUrl ( next ) ;
154- if ( syncTransportMode === " local" && next . trim ( ) . length > 0 ) {
155- setSyncTransportMode ( " hybrid" ) ;
166+ if ( syncTransportMode === ' local' && next . trim ( ) . length > 0 ) {
167+ setSyncTransportMode ( ' hybrid' ) ;
156168 }
157169 } }
158- placeholder = { `${ PLAYGROUND_PUBLIC_DISCOVERY_URL } or ws://localhost:8787/sync ` }
170+ placeholder = { `${ PLAYGROUND_PUBLIC_DISCOVERY_URL } or ws://localhost:8787` }
159171 spellCheck = { false }
160172 />
161173 < button
162174 type = "button"
163175 className = "rounded-md border border-slate-700 px-2 py-1.5 text-[11px] font-semibold text-slate-300 transition hover:border-slate-500 hover:text-white"
164176 onClick = { ( ) => {
165177 setSyncServerUrl ( PLAYGROUND_PUBLIC_DISCOVERY_URL ) ;
166- if ( syncTransportMode === " local" ) {
167- setSyncTransportMode ( " hybrid" ) ;
178+ if ( syncTransportMode === ' local' ) {
179+ setSyncTransportMode ( ' hybrid' ) ;
168180 }
169181 } }
170182 title = "Use the public emhub.net bootstrap endpoint"
@@ -174,7 +186,7 @@ export function PeersPanel({
174186 < button
175187 type = "button"
176188 className = "rounded-md border border-slate-700 px-2 py-1.5 text-[11px] font-semibold text-slate-300 transition hover:border-slate-500 hover:text-white disabled:opacity-50"
177- onClick = { ( ) => setSyncServerUrl ( "" ) }
189+ onClick = { ( ) => setSyncServerUrl ( '' ) }
178190 disabled = { syncServerUrl . trim ( ) . length === 0 }
179191 title = "Clear remote sync server URL"
180192 >
@@ -189,14 +201,18 @@ export function PeersPanel({
189201
190202 < div className = "mt-3 rounded-lg border border-slate-800/70 bg-slate-950/30 p-2" >
191203 < div className = "flex items-center justify-between gap-2" >
192- < div className = "text-[10px] font-semibold uppercase tracking-wide text-slate-400" > Connected peers</ div >
204+ < div className = "text-[10px] font-semibold uppercase tracking-wide text-slate-400" >
205+ Connected peers
206+ </ div >
193207 < div className = "text-[10px] text-slate-500" > { peers . length } </ div >
194208 </ div >
195209 < div className = "mt-2 max-h-32 overflow-auto pr-1" >
196210 { peers . map ( ( p ) => (
197211 < div key = { p . id } className = "flex items-center justify-between gap-2 py-1" >
198212 < span className = "font-mono text-slate-200" > { formatPeerId ( p . id ) } </ span >
199- < span className = "text-[10px] text-slate-500" > { Math . max ( 0 , Date . now ( ) - p . lastSeen ) } ms</ span >
213+ < span className = "text-[10px] text-slate-500" >
214+ { Math . max ( 0 , Date . now ( ) - p . lastSeen ) } ms
215+ </ span >
200216 </ div >
201217 ) ) }
202218 { peers . length === 0 && (
0 commit comments