Simplify demo: remove topics UI, ID-only connections

- Remove topic selection and peer discovery UI
- Remove MethodSelector and TopicsList components
- Simplify ConnectionForm to just take a connection ID
- Update to use @xtr-dev/rondevu-client@0.3.2
- Demo version: 0.3.2

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-12 23:18:05 +01:00
parent 1efe7346f4
commit eaf474a984
5 changed files with 49 additions and 199 deletions

12
package-lock.json generated
View File

@@ -1,14 +1,14 @@
{
"name": "rondevu-demo",
"version": "1.0.2",
"version": "0.3.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "rondevu-demo",
"version": "1.0.2",
"version": "0.3.2",
"dependencies": {
"@xtr-dev/rondevu-client": "^0.3.1",
"@xtr-dev/rondevu-client": "^0.3.2",
"@zxing/library": "^0.21.3",
"qrcode": "^1.5.4",
"react": "^18.2.0",
@@ -1170,9 +1170,9 @@
}
},
"node_modules/@xtr-dev/rondevu-client": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@xtr-dev/rondevu-client/-/rondevu-client-0.3.1.tgz",
"integrity": "sha512-KVbssIVFNyIE4kw1Ygj36Ag29TW3CtNJXgrBRbyt/vNS8Phe0i61J0Z2isEzZs+rkuncaE6TWxNzU5CMljhI5g==",
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/@xtr-dev/rondevu-client/-/rondevu-client-0.3.2.tgz",
"integrity": "sha512-qWQDP6L675bLksKrk8HYc1ZNoAe0X/1Fj92Lffh9HPHcoeME7ateXb0mD7KlPNNOem6u210q35FNTiJWuHEyuw==",
"license": "MIT"
},
"node_modules/@zxing/library": {

View File

@@ -1,6 +1,6 @@
{
"name": "rondevu-demo",
"version": "1.0.2",
"version": "0.3.2",
"description": "Demo application for Rondevu peer signaling and discovery",
"type": "module",
"scripts": {
@@ -10,7 +10,7 @@
"deploy": "npm run build && npx wrangler pages deploy dist --project-name=rondevu-demo"
},
"dependencies": {
"@xtr-dev/rondevu-client": "^0.3.1",
"@xtr-dev/rondevu-client": "^0.3.2",
"@zxing/library": "^0.21.3",
"qrcode": "^1.5.4",
"react": "^18.2.0",

View File

@@ -3,10 +3,8 @@ import { Rondevu } from '@xtr-dev/rondevu-client';
import QRCode from 'qrcode';
import Header from './components/Header';
import ActionSelector from './components/ActionSelector';
import MethodSelector from './components/MethodSelector';
import ConnectionForm from './components/ConnectionForm';
import ChatView from './components/ChatView';
import TopicsList from './components/TopicsList';
const rdv = new Rondevu({
baseUrl: 'https://api.ronde.vu',
@@ -35,17 +33,12 @@ function generateConnectionId() {
function App() {
// Step-based state
const [step, setStep] = useState(1); // 1: action, 2: method, 3: details, 4: connected
const [action, setAction] = useState(null); // 'create', 'join', or 'scan'
const [method, setMethod] = useState(null); // 'topic', 'peer-id', 'connection-id'
const [step, setStep] = useState(1); // 1: action, 2: details, 3: connected
const [action, setAction] = useState(null); // 'create' or 'connect'
const [qrCodeUrl, setQrCodeUrl] = useState('');
// Connection state
const [topic, setTopic] = useState('');
const [connectionId, setConnectionId] = useState('');
const [peerId, setPeerId] = useState('');
const [topics, setTopics] = useState([]);
const [sessions, setSessions] = useState([]);
const [connectionStatus, setConnectionStatus] = useState('disconnected');
const [connectedPeer, setConnectedPeer] = useState(null);
const [currentConnectionId, setCurrentConnectionId] = useState(null);
@@ -61,9 +54,6 @@ function App() {
const [demoVersion, setDemoVersion] = useState('unknown');
const [serverVersion, setServerVersion] = useState('unknown');
// Topics modal state
const [showTopicsList, setShowTopicsList] = useState(false);
const connectionRef = useRef(null);
const dataChannelRef = useRef(null);
const fileTransfersRef = useRef(new Map()); // Track ongoing file transfers
@@ -71,7 +61,6 @@ function App() {
useEffect(() => {
log('Demo initialized', 'info');
loadTopics();
loadVersions();
}, []);
@@ -93,32 +82,13 @@ function App() {
}
};
const loadTopics = async () => {
try {
const { topics } = await rdv.api.listTopics();
setTopics(topics);
} catch (error) {
log(`Error loading topics: ${error.message}`, 'error');
}
};
const discoverPeers = async (topicName) => {
try {
const { sessions: foundSessions } = await rdv.api.listSessions(topicName);
const otherSessions = foundSessions.filter(s => s.peerId !== rdv.peerId);
setSessions(otherSessions);
} catch (error) {
log(`Error discovering peers: ${error.message}`, 'error');
}
};
const setupConnection = (connection) => {
connectionRef.current = connection;
connection.on('connect', () => {
log('✅ Connected!', 'success');
setConnectionStatus('connected');
setStep(4);
setStep(3);
const channel = connection.dataChannel('chat');
setupDataChannel(channel);
@@ -176,17 +146,10 @@ function App() {
let connId;
if (action === 'create') {
if (method === 'connection-id') {
connId = connectionId || generateConnectionId();
connection = await rdv.create(connId, topic || 'default');
setCurrentConnectionId(connId);
log(`Created connection: ${connId}`, 'success');
} else {
connId = generateConnectionId();
connection = await rdv.create(connId, topic);
setCurrentConnectionId(connId);
log(`Created connection: ${connId}`, 'success');
}
connId = connectionId || generateConnectionId();
connection = await rdv.create(connId);
setCurrentConnectionId(connId);
log(`Created connection: ${connId}`, 'success');
// Generate QR code if creating a connection
try {
@@ -204,18 +167,8 @@ function App() {
log(`QR code generation error: ${err.message}`, 'error');
}
} else {
if (method === 'topic') {
connection = await rdv.join(topic);
setCurrentConnectionId(connection.id);
} else if (method === 'peer-id') {
connection = await rdv.join(topic, {
filter: (s) => s.peerId === peerId
});
setCurrentConnectionId(connection.id);
} else if (method === 'connection-id') {
connection = await rdv.connect(connectionId);
setCurrentConnectionId(connectionId);
}
connection = await rdv.connect(connectionId);
setCurrentConnectionId(connectionId);
}
setConnectedPeer(connection.remotePeerId || 'Waiting...');
@@ -435,11 +388,7 @@ function App() {
}
setStep(1);
setAction(null);
setMethod(null);
setTopic('');
setConnectionId('');
setPeerId('');
setSessions([]);
setConnectionStatus('disconnected');
setConnectedPeer(null);
setCurrentConnectionId(null);
@@ -452,9 +401,8 @@ function App() {
const handleScanComplete = (scannedId) => {
setConnectionId(scannedId);
setAction('join');
setMethod('connection-id');
setStep(3);
setAction('connect');
setStep(2);
};
const handleScanCancel = () => {
@@ -482,39 +430,19 @@ function App() {
)}
{step === 2 && (
<MethodSelector
<ConnectionForm
action={action}
onSelectMethod={(m) => {
setMethod(m);
setStep(3);
}}
connectionId={connectionId}
setConnectionId={setConnectionId}
connectionStatus={connectionStatus}
qrCodeUrl={qrCodeUrl}
currentConnectionId={currentConnectionId}
onConnect={handleConnect}
onBack={() => setStep(1)}
/>
)}
{step === 3 && (
<ConnectionForm
action={action}
method={method}
topic={topic}
setTopic={setTopic}
connectionId={connectionId}
setConnectionId={setConnectionId}
peerId={peerId}
setPeerId={setPeerId}
topics={topics}
sessions={sessions}
connectionStatus={connectionStatus}
qrCodeUrl={qrCodeUrl}
currentConnectionId={currentConnectionId}
onConnect={handleConnect}
onBack={() => setStep(2)}
onTopicSelect={setTopic}
onDiscoverPeers={discoverPeers}
/>
)}
{step === 4 && (
<ChatView
connectedPeer={connectedPeer}
currentConnectionId={currentConnectionId}
@@ -533,24 +461,6 @@ function App() {
)}
<div className="peer-id-badge">Your Peer ID: {rdv.peerId}</div>
{/* Floating button to view topics */}
{step !== 4 && (
<button
className="view-topics-button"
onClick={() => setShowTopicsList(true)}
>
📊 View Topics
</button>
)}
{/* Topics modal */}
{showTopicsList && (
<TopicsList
rdv={rdv}
onClose={() => setShowTopicsList(false)}
/>
)}
</main>
<footer className="footer">

View File

@@ -2,95 +2,31 @@ import QRCodeDisplay from './QRCodeDisplay';
function ConnectionForm({
action,
method,
topic,
setTopic,
connectionId,
setConnectionId,
peerId,
setPeerId,
topics,
sessions,
connectionStatus,
qrCodeUrl,
currentConnectionId,
onConnect,
onBack,
onTopicSelect,
onDiscoverPeers
onBack
}) {
return (
<div className="step-container">
<h2>Enter Details</h2>
<h2>{action === 'create' ? 'Create Connection' : 'Join Connection'}</h2>
<div className="form-container">
{(method === 'topic' || method === 'peer-id' || (method === 'connection-id' && action === 'create')) && (
<div className="form-group">
<label>Topic</label>
<input
type="text"
value={topic}
onChange={(e) => setTopic(e.target.value)}
placeholder="e.g., game-room"
autoFocus
/>
{topics.length > 0 && (
<div className="topic-list">
{topics.map((t) => (
<button
key={t.topic}
className="topic-item"
onClick={() => {
onTopicSelect(t.topic);
if (method === 'peer-id') {
onDiscoverPeers(t.topic);
}
}}
>
{t.topic} <span className="peer-count">({t.count})</span>
</button>
))}
</div>
)}
</div>
)}
{method === 'peer-id' && (
<div className="form-group">
<label>Peer ID</label>
<input
type="text"
value={peerId}
onChange={(e) => setPeerId(e.target.value)}
placeholder="e.g., player-123"
/>
{sessions.length > 0 && (
<div className="topic-list">
{sessions.map((s) => (
<button
key={s.code}
className="topic-item"
onClick={() => setPeerId(s.peerId)}
>
{s.peerId}
</button>
))}
</div>
)}
</div>
)}
{method === 'connection-id' && (
<div className="form-group">
<label>Connection ID {action === 'create' && '(optional)'}</label>
<input
type="text"
value={connectionId}
onChange={(e) => setConnectionId(e.target.value)}
placeholder={action === 'create' ? 'Auto-generated if empty' : 'e.g., meeting-123'}
autoFocus={action === 'join'}
/>
</div>
)}
<div className="form-group">
<label>Connection ID {action === 'create' && '(optional)'}</label>
<input
type="text"
value={connectionId}
onChange={(e) => setConnectionId(e.target.value)}
placeholder={action === 'create' ? 'Auto-generated if empty' : 'Enter connection ID'}
autoFocus={action === 'connect'}
/>
{action === 'create' && !connectionId && (
<p className="help-text">Leave empty to auto-generate a random ID</p>
)}
</div>
<div className="button-row">
<button className="back-button" onClick={onBack}> Back</button>
@@ -99,12 +35,10 @@ function ConnectionForm({
onClick={onConnect}
disabled={
connectionStatus === 'connecting' ||
(method === 'topic' && !topic) ||
(method === 'peer-id' && (!topic || !peerId)) ||
(method === 'connection-id' && action === 'join' && !connectionId)
(action === 'connect' && !connectionId)
}
>
{connectionStatus === 'connecting' ? 'Connecting...' : 'Connect'}
{connectionStatus === 'connecting' ? 'Connecting...' : (action === 'create' ? 'Create' : 'Connect')}
</button>
</div>

View File

@@ -162,6 +162,12 @@ body {
font-size: 0.95rem;
}
.help-text {
margin-top: 8px;
font-size: 0.85rem;
color: #6c757d;
}
input[type="text"] {
width: 100%;
padding: 12px 16px;