mirror of
https://github.com/xtr-dev/rondevu-demo.git
synced 2025-12-12 19:43:23 +00:00
Refactor app into components and add file upload progress
Components created: - Header: App header with GitHub links - ActionSelector: Step 1 - Choose create/join/scan - MethodSelector: Step 2 - Choose connection method - ConnectionForm: Step 3 - Enter connection details - ChatView: Step 4 - Connected chat interface - Message: Individual message display (text/file) - QRScanner: QR code scanning component - QRCodeDisplay: QR code display component - FileUploadProgress: Progress bar for file uploads Features: - Clean component separation with props - File upload progress bar with percentage - Cancel upload functionality - Disabled file button during upload - Visual progress indicator with gradient - All logic remains in App.jsx for state management
This commit is contained in:
99
src/components/ChatView.jsx
Normal file
99
src/components/ChatView.jsx
Normal file
@@ -0,0 +1,99 @@
|
||||
import { useRef } from 'react';
|
||||
import Message from './Message';
|
||||
import FileUploadProgress from './FileUploadProgress';
|
||||
|
||||
function ChatView({
|
||||
connectedPeer,
|
||||
currentConnectionId,
|
||||
messages,
|
||||
messageInput,
|
||||
setMessageInput,
|
||||
channelReady,
|
||||
logs,
|
||||
fileUploadProgress,
|
||||
onSendMessage,
|
||||
onFileSelect,
|
||||
onDisconnect,
|
||||
onDownloadFile,
|
||||
onCancelUpload
|
||||
}) {
|
||||
const fileInputRef = useRef(null);
|
||||
|
||||
return (
|
||||
<div className="chat-container">
|
||||
<div className="chat-header">
|
||||
<div>
|
||||
<h2>Connected</h2>
|
||||
<p className="connection-details">
|
||||
Peer: {connectedPeer || 'Unknown'} • ID: {currentConnectionId}
|
||||
</p>
|
||||
</div>
|
||||
<button className="disconnect-button" onClick={onDisconnect}>Disconnect</button>
|
||||
</div>
|
||||
|
||||
<div className="messages">
|
||||
{messages.length === 0 ? (
|
||||
<p className="empty">No messages yet. Start chatting!</p>
|
||||
) : (
|
||||
messages.map((msg, idx) => (
|
||||
<Message key={idx} message={msg} onDownload={onDownloadFile} />
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
|
||||
{fileUploadProgress && (
|
||||
<FileUploadProgress
|
||||
fileName={fileUploadProgress.fileName}
|
||||
progress={fileUploadProgress.progress}
|
||||
onCancel={onCancelUpload}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="message-input">
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
onChange={onFileSelect}
|
||||
style={{ display: 'none' }}
|
||||
/>
|
||||
<button
|
||||
className="file-button"
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
disabled={!channelReady || fileUploadProgress}
|
||||
title="Send file"
|
||||
>
|
||||
📎
|
||||
</button>
|
||||
<input
|
||||
type="text"
|
||||
value={messageInput}
|
||||
onChange={(e) => setMessageInput(e.target.value)}
|
||||
onKeyPress={(e) => e.key === 'Enter' && onSendMessage()}
|
||||
placeholder="Type a message..."
|
||||
disabled={!channelReady}
|
||||
/>
|
||||
<button
|
||||
onClick={onSendMessage}
|
||||
disabled={!channelReady}
|
||||
>
|
||||
Send
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{logs.length > 0 && (
|
||||
<details className="logs">
|
||||
<summary>Activity Log ({logs.length})</summary>
|
||||
<div className="log-entries">
|
||||
{logs.map((log, idx) => (
|
||||
<div key={idx} className={`log-entry ${log.type}`}>
|
||||
[{log.timestamp}] {log.message}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</details>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ChatView;
|
||||
Reference in New Issue
Block a user