/ concept-collection / commonview
concept-collection / commonview
commonview / src / App.tsx
72 lines · 2.5 KBBlameHistoryRaw
1import {useNetwork} from './useNetwork'
3const short = (id: string) => id.slice(0, 8) + '…' + id.slice(-4)
5const time = (ms: number) => new Date(ms).toLocaleTimeString()
7export default function App() {
8 const {snapshot, dispatch} = useNetwork()
9 const {selfId, connectedAt, centralId, amCentral, roster, state, version} =
10 snapshot
12 return (
13 <div style={{fontFamily: 'sans-serif', maxWidth: 640, margin: '2rem auto', padding: '0 1rem'}}>
14 <h1>CommonView</h1>
16 <section>
17 <h2>You</h2>
18 <div>ID: <code>{short(selfId)}</code></div>
19 <div>Connected at: {time(connectedAt)}</div>
20 <div>
21 Role:{' '}
22 <strong>{amCentral ? 'CENTRAL (source of truth)' : 'peer'}</strong>
23 </div>
24 <div>
25 Central peer:{' '}
26 <code>{centralId ? short(centralId) : '(none)'}</code>
27 </div>
28 </section>
30 <section>
31 <h2>Shared state</h2>
32 <div style={{fontSize: '2rem'}}>counter = {state.counter}</div>
33 <div style={{color: '#666', fontSize: '0.85rem'}}>version {version}</div>
34 <div style={{marginTop: '0.5rem'}}>
35 <button onClick={() => dispatch({op: 'decrement'})}>−</button>{' '}
36 <button onClick={() => dispatch({op: 'increment'})}>+</button>
37 </div>
38 <p style={{color: '#666', fontSize: '0.85rem'}}>
39 Commands are sent to the central peer, which updates the authoritative
40 state and broadcasts it back to everyone.
41 </p>
42 </section>
44 <section>
45 <h2>Peers in room ({roster.length})</h2>
46 <table style={{borderCollapse: 'collapse', width: '100%'}}>
47 <thead>
48 <tr style={{textAlign: 'left'}}>
49 <th style={{padding: '0.25rem'}}>ID</th>
50 <th style={{padding: '0.25rem'}}>Connected</th>
51 <th style={{padding: '0.25rem'}}>Role</th>
52 </tr>
53 </thead>
54 <tbody>
55 {roster.map(p => (
56 <tr key={p.peerId} style={{background: p.isSelf ? '#f0f0f0' : undefined}}>
57 <td style={{padding: '0.25rem'}}>
58 <code>{short(p.peerId)}</code>
59 {p.isSelf ? ' (you)' : ''}
60 </td>
61 <td style={{padding: '0.25rem'}}>{time(p.connectedAt)}</td>
62 <td style={{padding: '0.25rem'}}>
63 {p.isCentral ? 'central' : 'peer'}
64 </td>
65 </tr>
66 ))}
67 </tbody>
68 </table>
69 </section>
70 </div>
71 )