@diyawanna/lan-bridge-core
Version:
A module for LAN-based bi-directional communication between web and mobile applications using WebSockets.
204 lines (188 loc) • 8.33 kB
JSX
import React, { useState, useEffect, useRef } from 'react';
const LANBridgeComponent = ({ serverUrl = 'ws://localhost:8080' }) => {
const [isConnected, setIsConnected] = useState(false);
const [messages, setMessages] = useState([]);
const [textInput, setTextInput] = useState('');
const bridgeRef = useRef(null);
const fileInputRef = useRef(null);
useEffect(() => {
// Import the LANBridge client
const script = document.createElement('script');
script.src = '/client.js'; // Assuming client.js is served from public folder
script.onload = () => {
bridgeRef.current = new window.LANBridge(serverUrl);
// Set up message handlers
bridgeRef.current.onMessage('text', (message) => {
setMessages(prev => [...prev, {
id: Date.now(),
type: 'text',
content: message.payload,
timestamp: new Date().toLocaleTimeString()
}]);
});
bridgeRef.current.onMessage('image', (message) => {
setMessages(prev => [...prev, {
id: Date.now(),
type: 'image',
content: message.name,
path: message.path,
timestamp: new Date().toLocaleTimeString()
}]);
});
bridgeRef.current.onMessage('file', (message) => {
setMessages(prev => [...prev, {
id: Date.now(),
type: 'file',
content: message.name,
path: message.path,
timestamp: new Date().toLocaleTimeString()
}]);
});
// Connect to server
bridgeRef.current.connect()
.then(() => setIsConnected(true))
.catch(err => console.error('Connection failed:', err));
};
document.head.appendChild(script);
return () => {
if (bridgeRef.current) {
bridgeRef.current.disconnect();
}
document.head.removeChild(script);
};
}, [serverUrl]);
const sendText = () => {
if (textInput.trim() && bridgeRef.current) {
bridgeRef.current.sendText(textInput);
setMessages(prev => [...prev, {
id: Date.now(),
type: 'text',
content: textInput,
timestamp: new Date().toLocaleTimeString(),
sent: true
}]);
setTextInput('');
}
};
const sendFile = (event) => {
const file = event.target.files[0];
if (file && bridgeRef.current) {
bridgeRef.current.sendFile(file)
.then(() => {
setMessages(prev => [...prev, {
id: Date.now(),
type: file.type.startsWith('image/') ? 'image' : 'file',
content: file.name,
timestamp: new Date().toLocaleTimeString(),
sent: true
}]);
})
.catch(err => console.error('File send failed:', err));
}
event.target.value = ''; // Reset file input
};
return (
<div className="lan-bridge-core-container" style={{ maxWidth: '600px', margin: '0 auto', padding: '20px' }}>
<div className="connection-status" style={{
padding: '10px',
borderRadius: '5px',
marginBottom: '20px',
backgroundColor: isConnected ? '#d4edda' : '#f8d7da',
color: isConnected ? '#155724' : '#721c24'
}}>
Status: {isConnected ? 'Connected' : 'Disconnected'}
</div>
<div className="input-section" style={{ marginBottom: '20px' }}>
<div style={{ display: 'flex', gap: '10px', marginBottom: '10px' }}>
<input
type="text"
value={textInput}
onChange={(e) => setTextInput(e.target.value)}
placeholder="Enter text message..."
style={{ flex: 1, padding: '10px', borderRadius: '5px', border: '1px solid #ccc' }}
onKeyPress={(e) => e.key === 'Enter' && sendText()}
/>
<button
onClick={sendText}
disabled={!isConnected}
style={{
padding: '10px 20px',
borderRadius: '5px',
border: 'none',
backgroundColor: '#007bff',
color: 'white',
cursor: isConnected ? 'pointer' : 'not-allowed'
}}
>
Send Text
</button>
</div>
<div>
<input
type="file"
ref={fileInputRef}
onChange={sendFile}
style={{ display: 'none' }}
/>
<button
onClick={() => fileInputRef.current?.click()}
disabled={!isConnected}
style={{
padding: '10px 20px',
borderRadius: '5px',
border: 'none',
backgroundColor: '#28a745',
color: 'white',
cursor: isConnected ? 'pointer' : 'not-allowed'
}}
>
Send File/Image
</button>
</div>
</div>
<div className="messages-section">
<h3>Messages</h3>
<div style={{
height: '400px',
overflowY: 'auto',
border: '1px solid #ccc',
borderRadius: '5px',
padding: '10px'
}}>
{messages.map(message => (
<div
key={message.id}
style={{
marginBottom: '10px',
padding: '10px',
borderRadius: '5px',
backgroundColor: message.sent ? '#e3f2fd' : '#f5f5f5',
textAlign: message.sent ? 'right' : 'left'
}}
>
<div style={{ fontWeight: 'bold', fontSize: '12px', color: '#666' }}>
{message.sent ? 'Sent' : 'Received'} - {message.timestamp}
</div>
<div style={{ marginTop: '5px' }}>
{message.type === 'text' && <span>{message.content}</span>}
{message.type === 'image' && (
<div>
<span>Image: {message.content}</span>
{message.path && <img src={message.path} alt={message.content} style={{ maxWidth: '200px', display: 'block', marginTop: '5px' }} />}
</div>
)}
{message.type === 'file' && (
<div>
<span>File: {message.content}</span>
{message.path && <a href={message.path} download style={{ display: 'block', marginTop: '5px' }}>Download</a>}
</div>
)}
</div>
</div>
))}
</div>
</div>
</div>
);
};
export default LANBridgeComponent;