Spaces:
Running
Running
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Stranger Chat</title> | |
<style> | |
/* | |
================================================================================ | |
V3: ADAPTIVE CSS FOR MOBILE & DESKTOP | |
================================================================================ | |
*/ | |
/* --- 1. Mobile-First Base Styles (Default) --- */ | |
/* These styles apply to all screens, optimized for mobile. */ | |
:root { | |
--header-bg: #005e54; | |
--chat-bg: #e5ddd5; | |
--bubble-me-bg: #dcf8c6; | |
--bubble-other-bg: #ffffff; | |
--input-bg: #f0f0f0; | |
--primary-text: #075e54; | |
--secondary-text: #667781; | |
--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | |
} | |
html { | |
/* Set a larger base font size for mobile readability */ | |
font-size: 1.0em; | |
} | |
body { | |
font-family: var(--font-family); | |
background: #e9eaed; /* A neutral desktop background */ | |
margin: 0; | |
padding: 0; | |
color: #333; | |
} | |
/* Hide chat by default */ | |
#chat { | |
display: none; | |
} | |
/* --- Mobile Containers: Full Screen --- */ | |
#lobby, #chat { | |
height: 100vh; | |
width: 100%; | |
margin: 0; | |
border-radius: 0; | |
box-shadow: none; | |
box-sizing: border-box; | |
flex-direction: column; | |
} | |
#lobby { | |
background: white; | |
justify-content: center; | |
padding: 1.5rem; | |
} | |
/* --- Mobile Forms & Inputs: Larger for Touch --- */ | |
#lobby h2 { | |
color: var(--primary-text); | |
text-align: center; | |
} | |
#lobby input, #lobby select, #lobby button { | |
width: 100%; | |
padding: 1.1rem; /* More padding for easier tapping */ | |
margin: 0.5rem 0; | |
box-sizing: border-box; | |
border: 1px solid #ccc; | |
border-radius: 8px; | |
font-size: 1rem; | |
} | |
#lobby button { | |
background-color: var(--header-bg); | |
color: white; | |
font-weight: bold; | |
border: none; | |
cursor: pointer; | |
} | |
#lobbyStatus { | |
text-align: center; | |
margin-top: 1rem; | |
color: var(--secondary-text); | |
} | |
/* --- Chat UI Styling (Mobile) --- */ | |
#chat { | |
background: var(--chat-bg); | |
overflow: hidden; | |
} | |
#chatHeader { | |
flex-shrink: 0; | |
background: var(--header-bg); | |
color: white; | |
font-weight: 600; | |
font-size: 1.1rem; | |
padding: 1rem; | |
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); | |
z-index: 10; | |
text-align: center; | |
} | |
#messages { | |
flex-grow: 1; | |
overflow-y: auto; | |
padding: 1rem 0.75rem; | |
display: flex; | |
flex-direction: column; | |
gap: 0.3rem; | |
} | |
#messages div { | |
padding: 0.6rem 0.9rem; | |
border-radius: 12px; | |
max-width: 85%; | |
word-wrap: break-word; | |
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.08); | |
line-height: 1.4; | |
font-size: 1rem; /* Base this on the root html font-size */ | |
} | |
.me { | |
align-self: flex-end; | |
background-color: var(--bubble-me-bg); | |
border-bottom-right-radius: 2px; | |
} | |
.other { | |
align-self: flex-start; | |
background-color: var(--bubble-other-bg); | |
border-bottom-left-radius: 2px; | |
} | |
.status { | |
align-self: center; | |
background-color: rgba(0, 0, 0, 0.1); | |
color: white; | |
font-size: 0.8rem; | |
font-style: normal; | |
font-weight: 500; | |
padding: 0.4rem 0.8rem; | |
box-shadow: none; | |
border-radius: 20px; | |
} | |
#input-area { | |
flex-shrink: 0; | |
display: flex; | |
align-items: center; | |
padding: 0.6rem 0.75rem; | |
background-color: var(--input-bg); | |
} | |
#msg { | |
flex-grow: 1; | |
border: none; | |
padding: 0.9rem 1.1rem; | |
border-radius: 2rem; | |
font-size: 1rem; | |
margin-right: 0.6rem; | |
background: white; | |
} | |
#msg:focus { | |
outline: none; | |
} | |
button { | |
border: none; | |
cursor: pointer; | |
background: transparent; | |
color: white; | |
font-size: 1rem; | |
font-weight: bold; | |
} | |
#send { | |
background-color: var(--header-bg); | |
min-width: 50px; | |
min-height: 50px; | |
border-radius: 50%; | |
padding: 0; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
} | |
#leave { | |
width: 100%; | |
padding: 0.5rem; | |
color: var(--secondary-text); | |
background-color: var(--input-bg); | |
text-align: center; | |
font-size: 0.9rem; | |
font-weight: normal; | |
flex-shrink: 0; | |
} | |
/* --- 2. Desktop Overrides --- */ | |
/* These styles apply ONLY when screen width is 768px or more. */ | |
@media (orientation: landscape) { | |
html { | |
/* Reset to a standard desktop font size */ | |
font-size: 1em; | |
} | |
/* Create a centered, windowed look for containers */ | |
#lobby, #chat { | |
height: auto; | |
margin: 2rem auto; | |
border-radius: 12px; | |
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.15); | |
} | |
#lobby { | |
max-width: 450px; /* Constrain lobby width */ | |
min-height: 0; | |
padding: 2rem; | |
} | |
#chat { | |
max-width: 80%; | |
height: calc(100vh - 4rem); /* Fill most of the screen but not all */ | |
max-height: 900px; /* Set a max-height */ | |
} | |
#leave { | |
background-color: white; /* Match background on desktop */ | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div id="lobby"> | |
<h2>Create Profile & Join</h2> | |
<form id="form"> | |
ID: <input name="id" required><br> | |
Gender: | |
<select name="gender"><option>Male</option><option>Female</option></select><br> | |
Age: <input name="age" type="number" required><br> | |
Interests:<br> | |
<label><input type="checkbox" name="interests" value="science">Science</label><br> | |
<label><input type="checkbox" name="interests" value="arts">Arts</label><br> | |
<label><input type="checkbox" name="interests" value="life">Life</label><br> | |
Looking for: | |
<select name="looking"> | |
<option value="any">Any</option> | |
<option value="male">Male</option> | |
<option value="female">Female</option> | |
</select><br> | |
<button>Enter Lobby</button> | |
</form> | |
<div id="lobbyStatus"></div> | |
</div> | |
<div id="chat"> | |
<div id="chatHeader">Chat Room</div> | |
<div id="messages"></div> | |
<div id="input-area"> | |
<input id="msg" autocomplete="off" placeholder="Type a message..."> | |
<button id="send">Send</button> | |
</div> | |
<button id="leave">Leave</button> | |
</div> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.8.1/socket.io.js"></script> | |
<script> | |
const socket = io(); | |
const form = document.getElementById("form"); | |
const lobby = document.getElementById("lobby"); | |
const lobbyStatus = document.getElementById("lobbyStatus"); | |
const chatDiv = document.getElementById("chat"); | |
const messages = document.getElementById("messages"); | |
const input = document.getElementById("msg"); | |
const sendBtn = document.getElementById("send"); | |
const leaveBtn = document.getElementById("leave"); | |
const chatHeader = document.getElementById("chatHeader"); | |
let currentRoom = null; | |
let myId = null; | |
let mySid = null; | |
let partnerId = null; | |
let partnerSid = null; | |
form.addEventListener("submit", e => { | |
e.preventDefault(); | |
const data = new FormData(form); | |
myId = data.get("id"); | |
const profile = { | |
id: data.get("id"), | |
gender: data.get("gender"), | |
age: data.get("age"), | |
looking: data.get("looking"), | |
interests: data.getAll("interests") | |
}; | |
lobbyStatus.textContent = "Finding partner..."; | |
socket.emit("find", profile); | |
}); | |
socket.on("status", d => { | |
lobbyStatus.textContent = d.msg; | |
appendMessage(d.msg, "status"); | |
}); | |
socket.on("matched", d => { | |
currentRoom = d.room; | |
mySid = socket.id; | |
myId = d.my_id; | |
partnerId = d.partner_id; | |
partnerSid = d.partner_sid; | |
lobby.style.display = "none"; | |
chatDiv.style.display = "flex"; // Changed from 'block' to 'flex' | |
chatHeader.textContent = `Chatroom of ${myId} and ${partnerId}`; | |
appendMessage("Matched! Start chatting.", "status"); | |
}); | |
// Allow sending message with Enter key | |
input.addEventListener("keypress", (e) => { | |
if (e.key === "Enter") { | |
e.preventDefault(); // Prevents new line in input | |
sendBtn.onclick(); | |
} | |
}); | |
sendBtn.onclick = () => { | |
const txt = input.value.trim(); | |
if (!txt || !currentRoom) return; | |
socket.emit("chat", { room: currentRoom, msg: txt, sid: mySid }); | |
input.value = ""; | |
input.focus(); // Keep focus on the input after sending | |
}; | |
socket.on("chat", d => { | |
const who = d.sid === mySid ? "You" : partnerId || "Partner"; | |
const cls = d.sid === mySid ? "me" : "other"; | |
appendMessage(`${who}: ${d.msg}`, cls); | |
}); | |
leaveBtn.onclick = () => { | |
if (confirm("Leave?")) socket.emit("leave", { room: currentRoom }); | |
}; | |
socket.on("left", () => { | |
appendMessage("You left the chat.", "status"); | |
setTimeout(() => location.reload(), 1000); | |
}); | |
function appendMessage(text, cls = "chat") { | |
const d = document.createElement("div"); | |
d.textContent = text; | |
if (cls) d.classList.add(cls); | |
messages.append(d); | |
messages.scrollTop = messages.scrollHeight; | |
} | |
</script> | |
</body> | |
</html> |