@@ -26,6 +26,13 @@ const LobbyScreen = () => {
|
|||||||
|
|
||||||
const handleJoinRoom = useCallback((data) => {
|
const handleJoinRoom = useCallback((data) => {
|
||||||
const { email, room } = data;
|
const { email, room } = data;
|
||||||
|
|
||||||
|
// Store user session data
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
localStorage.setItem('userEmail', email);
|
||||||
|
localStorage.setItem('currentRoom', room);
|
||||||
|
}
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
router.push(`/room/${room}`);
|
router.push(`/room/${room}`);
|
||||||
}, [router]);
|
}, [router]);
|
||||||
@@ -34,6 +41,7 @@ const LobbyScreen = () => {
|
|||||||
socket.on("room:join", handleJoinRoom);
|
socket.on("room:join", handleJoinRoom);
|
||||||
socket.on("error", (error) => {
|
socket.on("error", (error) => {
|
||||||
console.error('Socket error:', error);
|
console.error('Socket error:', error);
|
||||||
|
alert(`Error: ${error.message || 'Failed to join room. Please check your room ID format (letters, numbers, hyphens, underscores only).'}`);
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -121,9 +129,9 @@ const LobbyScreen = () => {
|
|||||||
required
|
required
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
value={room}
|
value={room}
|
||||||
onChange={(e) => setRoom(e.target.value)}
|
onChange={(e) => setRoom(e.target.value.replace(/[^a-zA-Z0-9-_]/g, ''))}
|
||||||
className="w-full px-4 py-3 border border-gray-200 rounded-xl focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all duration-200 bg-white/50 backdrop-blur-sm"
|
className="w-full px-4 py-3 border border-gray-200 rounded-xl focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-all duration-200 bg-white/50 backdrop-blur-sm"
|
||||||
placeholder="Enter room ID"
|
placeholder="Enter room ID (letters, numbers, -, _)"
|
||||||
disabled={isLoading}
|
disabled={isLoading}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -20,6 +20,46 @@ const RoomPage = () => {
|
|||||||
const [callButton, setCallButton] = useState(true);
|
const [callButton, setCallButton] = useState(true);
|
||||||
const [isSendButtonVisible, setIsSendButtonVisible] = useState(true);
|
const [isSendButtonVisible, setIsSendButtonVisible] = useState(true);
|
||||||
const [isConnecting, setIsConnecting] = useState(false);
|
const [isConnecting, setIsConnecting] = useState(false);
|
||||||
|
const [hasJoinedRoom, setHasJoinedRoom] = useState(false);
|
||||||
|
|
||||||
|
// Check if user came from lobby (has proper session) or direct navigation
|
||||||
|
useEffect(() => {
|
||||||
|
// Check if user has a valid session or email stored (you might want to implement proper session management)
|
||||||
|
const hasValidSession = localStorage.getItem('userEmail') || document.referrer.includes('/');
|
||||||
|
|
||||||
|
if (!hasValidSession && typeof window !== 'undefined') {
|
||||||
|
// User navigated directly to room page without going through lobby
|
||||||
|
console.warn('Direct navigation to room detected, redirecting to lobby');
|
||||||
|
router.push('/');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If user has a session, mark as joined
|
||||||
|
setHasJoinedRoom(true);
|
||||||
|
}, [router]);
|
||||||
|
|
||||||
|
// Store user email when they join from lobby
|
||||||
|
useEffect(() => {
|
||||||
|
socket.on("room:join", (data) => {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
localStorage.setItem('userEmail', data.email);
|
||||||
|
localStorage.setItem('currentRoom', data.room);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Listen for socket errors and provide user feedback
|
||||||
|
socket.on("error", (error) => {
|
||||||
|
console.error('Socket error:', error);
|
||||||
|
alert(`Connection Error: ${error.message || 'Something went wrong. Please try again.'}`);
|
||||||
|
// Redirect to lobby on error
|
||||||
|
router.push('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
socket.off("room:join");
|
||||||
|
socket.off("error");
|
||||||
|
};
|
||||||
|
}, [socket, router]);
|
||||||
|
|
||||||
const handleUserJoined = useCallback(({ email, id }) => {
|
const handleUserJoined = useCallback(({ email, id }) => {
|
||||||
console.log(`User ${email} joined the room!`);
|
console.log(`User ${email} joined the room!`);
|
||||||
@@ -225,11 +265,27 @@ const RoomPage = () => {
|
|||||||
|
|
||||||
const handleGoBack = () => {
|
const handleGoBack = () => {
|
||||||
handleEndCall();
|
handleEndCall();
|
||||||
|
|
||||||
|
// Clear session data when leaving room
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
localStorage.removeItem('userEmail');
|
||||||
|
localStorage.removeItem('currentRoom');
|
||||||
|
}
|
||||||
|
|
||||||
router.push('/');
|
router.push('/');
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='min-h-screen bg-gradient-to-br from-gray-900 via-blue-900 to-indigo-900 relative overflow-hidden'>
|
<>
|
||||||
|
{!hasJoinedRoom ? (
|
||||||
|
<div className="min-h-screen bg-gradient-to-br from-gray-900 via-blue-900 to-indigo-900 flex items-center justify-center">
|
||||||
|
<div className="text-center text-white">
|
||||||
|
<div className="animate-spin rounded-full h-8 w-8 border-2 border-white border-t-transparent mx-auto mb-4"></div>
|
||||||
|
<p>Verifying access...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className='min-h-screen bg-gradient-to-br from-gray-900 via-blue-900 to-indigo-900 relative overflow-hidden'>
|
||||||
<title>Room {slug} - VideoPeersJS</title>
|
<title>Room {slug} - VideoPeersJS</title>
|
||||||
|
|
||||||
{/* Background decorative elements */}
|
{/* Background decorative elements */}
|
||||||
@@ -385,6 +441,8 @@ const RoomPage = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ const io = new Server(server, {
|
|||||||
// Validation schemas
|
// Validation schemas
|
||||||
const roomJoinSchema = Joi.object({
|
const roomJoinSchema = Joi.object({
|
||||||
email: Joi.string().email().required(),
|
email: Joi.string().email().required(),
|
||||||
room: Joi.string().alphanum().min(3).max(50).required()
|
room: Joi.string().pattern(/^[a-zA-Z0-9-_]+$/).min(3).max(50).required()
|
||||||
});
|
});
|
||||||
|
|
||||||
const callSchema = Joi.object({
|
const callSchema = Joi.object({
|
||||||
@@ -121,7 +121,13 @@ io.on("connection", (socket) => {
|
|||||||
// Validate input
|
// Validate input
|
||||||
const { error, value } = roomJoinSchema.validate(data);
|
const { error, value } = roomJoinSchema.validate(data);
|
||||||
if (error) {
|
if (error) {
|
||||||
socket.emit("error", { message: "Invalid room join data" });
|
let errorMessage = "Invalid room join data";
|
||||||
|
if (error.details[0]?.context?.key === 'room') {
|
||||||
|
errorMessage = "Room ID must contain only letters, numbers, hyphens, and underscores (3-50 characters)";
|
||||||
|
} else if (error.details[0]?.context?.key === 'email') {
|
||||||
|
errorMessage = "Please provide a valid email address";
|
||||||
|
}
|
||||||
|
socket.emit("error", { message: errorMessage });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Referencia en una nueva incidencia
Block a user