Initial commit
This commit is contained in:
BIN
resource/.DS_Store
vendored
Normal file
BIN
resource/.DS_Store
vendored
Normal file
Binary file not shown.
156
resource/static/css/styles.css
Normal file
156
resource/static/css/styles.css
Normal file
@@ -0,0 +1,156 @@
|
||||
:root {
|
||||
--primary-color: rgb(243, 243, 243);
|
||||
--secondary-color: rgb(7, 190, 187);
|
||||
--tertiary-color: rgb(250, 250, 250);
|
||||
--text-color: rgb(62, 62, 62);
|
||||
--text-highlight-color: white;
|
||||
}
|
||||
|
||||
/* Navigation */
|
||||
.navbar {
|
||||
position: fixed;
|
||||
top:0px;
|
||||
left:0px;
|
||||
right:0px;
|
||||
background-color: var(--tertiary-color);
|
||||
border-bottom: 1px solid var(--secondary-color); /* Changed color to lightsteelblue */
|
||||
overflow: hidden;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.navbar a {
|
||||
float: left;
|
||||
display: block;
|
||||
text-align: center;
|
||||
padding: 8px 16px;
|
||||
text-decoration: none;
|
||||
transition: background-color 0.15s ease, color 0.15s ease, padding 0.15s ease; /* Only transition the background-color */
|
||||
color: var(--text-color); /* Set default text color */
|
||||
}
|
||||
|
||||
.navbar a:hover {
|
||||
background-color: var(--secondary-color);
|
||||
color: var(--text-highlight-color); /* Change text color on hover for better contrast */
|
||||
padding: 8px 20px; /* Increase padding on hover */
|
||||
}
|
||||
|
||||
.navname{
|
||||
font-weight: bolder;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.navname a{
|
||||
background-color: var(--primary-color) !important;
|
||||
}
|
||||
|
||||
/* Body */
|
||||
body {
|
||||
background-color: var(--primary-color);
|
||||
margin: 0px;
|
||||
color: var(--text-color);
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
/* Container */
|
||||
.container {
|
||||
padding: 35px 10px;
|
||||
margin: auto;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.room-join-box {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.room-input {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid var(--secondary-color);
|
||||
border-radius: 5px;
|
||||
background-color: var(--tertiary-color);
|
||||
color: var(--text-color);
|
||||
font-size: 16px;
|
||||
outline: none;
|
||||
transition: padding 0.15s ease, border-color 0.15s ease;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.room-input:focus {
|
||||
border-color: var(--secondary-color);
|
||||
padding-right: 14px;
|
||||
}
|
||||
|
||||
.room-button {
|
||||
padding: 8px 16px;
|
||||
background-color: var(--tertiary-color);
|
||||
border: 1px solid var(--secondary-color);
|
||||
border-radius: 5px;
|
||||
color: var(--text-color);
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.15s ease, color 0.15s ease, padding 0.15s ease;
|
||||
}
|
||||
|
||||
.room-button:hover {
|
||||
background-color: var(--secondary-color);
|
||||
color: var(--text-highlight-color);
|
||||
padding-left: 18px;
|
||||
padding-right: 18px;
|
||||
}
|
||||
|
||||
#chat-box {
|
||||
flex: 1; /* This is the key: allows chat-box to grow and fill vertical space */
|
||||
overflow-y: auto; /* Adds a scrollbar when content overflows vertically */
|
||||
padding: 10px;
|
||||
border: 1px solid var(--secondary-color); /* Visual border for chat box */
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px; /* Space between chat box and input */
|
||||
background-color: var(--tertiary-color); /* Example background for messages */
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#chat-box p {
|
||||
margin: 0 0 5px 0; /* Adjust message spacing */
|
||||
line-height: 1.4;
|
||||
word-wrap: break-word; /* Ensures long words break and wrap */
|
||||
}
|
||||
|
||||
.chat-input-container {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#chat-input {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid var(--secondary-color);
|
||||
border-radius: 5px;
|
||||
background-color: var(--tertiary-color);
|
||||
color: var(--text-color);
|
||||
font-size: 16px;
|
||||
outline: none;
|
||||
transition: padding 0.15s ease, border-color 0.15s ease;
|
||||
flex: 1; /* Makes the input take up available horizontal space */
|
||||
}
|
||||
|
||||
#send-button {
|
||||
padding: 8px 16px;
|
||||
background-color: var(--tertiary-color);
|
||||
border: 1px solid var(--secondary-color);
|
||||
border-radius: 5px;
|
||||
color: var(--text-color);
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.15s ease, color 0.15s ease, padding 0.15s ease;
|
||||
flex-shrink: 0; /* Prevents the button from shrinking */
|
||||
}
|
||||
|
||||
#send-button:hover {
|
||||
background-color: var(--secondary-color);
|
||||
color: var(--text-highlight-color);
|
||||
padding-left: 18px;
|
||||
padding-right: 18px;
|
||||
}
|
||||
18
resource/template/base.html
Normal file
18
resource/template/base.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
|
||||
<link rel="icon" href="data:,">
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
</head>
|
||||
<body>
|
||||
{% include 'navbar.html' %}
|
||||
|
||||
<div class="container">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
63
resource/template/home.html
Normal file
63
resource/template/home.html
Normal file
@@ -0,0 +1,63 @@
|
||||
{% extends 'base.html' %}
|
||||
{% block title %}Home{% endblock %}
|
||||
{% block content %}
|
||||
<h1>Hello, hello, hello...</h1>
|
||||
<p>Yeah, it's early.</p>
|
||||
<div class="room-join-box">
|
||||
<input type="text" id="username-input" class="room-input" placeholder="Your name">
|
||||
</div>
|
||||
|
||||
<div class="room-join-box">
|
||||
<input type="text" id="room-code-input" class="room-input" placeholder="Enter Room Code" maxlength="10">
|
||||
<button class="room-button" id="join-button">Join</button>
|
||||
</div>
|
||||
|
||||
<div class="room-join-box">
|
||||
<button class="room-button" id="create-button">Create New Room</button>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
function getUsername() {
|
||||
const username = document.getElementById('username-input').value.trim();
|
||||
if (!username) {
|
||||
alert("Please enter your name.");
|
||||
throw new Error("Username required");
|
||||
}
|
||||
localStorage.setItem('username', username);
|
||||
return username;
|
||||
}
|
||||
|
||||
document.getElementById('join-button').addEventListener('click', () => {
|
||||
try {
|
||||
getUsername();
|
||||
const code = document.getElementById('room-code-input').value.trim();
|
||||
if (code) {
|
||||
window.location.href = `/room/${code}`;
|
||||
} else {
|
||||
alert("Enter a room code.");
|
||||
}
|
||||
} catch (_) {}
|
||||
});
|
||||
|
||||
document.getElementById('create-button').addEventListener('click', async () => {
|
||||
try {
|
||||
getUsername();
|
||||
const res = await fetch('/api/room', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({})
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.code) {
|
||||
window.location.href = `/room/${data.code}`;
|
||||
} else {
|
||||
alert("Failed to create room.");
|
||||
}
|
||||
} catch (_) {}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
5
resource/template/navbar.html
Normal file
5
resource/template/navbar.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<div class="navbar">
|
||||
<a class="navname">Echo</a>
|
||||
<a href="/">Home</a>
|
||||
</div>
|
||||
|
||||
0
resource/template/options.html
Normal file
0
resource/template/options.html
Normal file
66
resource/template/room.html
Normal file
66
resource/template/room.html
Normal file
@@ -0,0 +1,66 @@
|
||||
{% extends 'room_base.html' %}
|
||||
{% block title %}Room {{ room_code }}{% endblock %}
|
||||
{% block content %}
|
||||
<h1>Room {{ room_code }}</h1>
|
||||
<div id="chat-box"></div>
|
||||
|
||||
<div class="chat-input-container">
|
||||
<input type="text" id="chat-input" placeholder="Say something..." />
|
||||
<button id="send-button">Send</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const socket = io();
|
||||
const room = "{{ room_code }}";
|
||||
|
||||
const name = localStorage.getItem('username') || 'Anonymous';
|
||||
socket.emit('join', { room, sender: name });
|
||||
|
||||
|
||||
// Fetch message history
|
||||
fetch(`/api/room/${room}/messages`)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
const chatBox = document.getElementById('chat-box');
|
||||
if (data && Array.isArray(data)) {
|
||||
data.forEach(msg => {
|
||||
const msgElem = document.createElement('p');
|
||||
msgElem.textContent = `${msg.sender}: ${msg.text}`;
|
||||
chatBox.appendChild(msgElem);
|
||||
});
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
}
|
||||
});
|
||||
|
||||
// Message listener
|
||||
socket.on('message', (data) => {
|
||||
const chatBox = document.getElementById('chat-box');
|
||||
const msgElem = document.createElement('p');
|
||||
|
||||
msgElem.textContent = `${data.sender}: ${data.text}`;
|
||||
if (data.sender === 'System') {
|
||||
msgElem.style.fontStyle = 'italic';
|
||||
msgElem.style.color = 'gray';
|
||||
}
|
||||
|
||||
chatBox.appendChild(msgElem);
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
});
|
||||
|
||||
|
||||
// Send message
|
||||
document.getElementById('send-button').onclick = () => {
|
||||
const text = document.getElementById('chat-input').value;
|
||||
const sender = localStorage.getItem('username') || 'Anonymous';
|
||||
|
||||
if (text.trim()) {
|
||||
socket.emit('message', {
|
||||
room,
|
||||
text,
|
||||
sender
|
||||
});
|
||||
document.getElementById('chat-input').value = '';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
{% endblock %}
|
||||
20
resource/template/room_base.html
Normal file
20
resource/template/room_base.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
|
||||
<link rel="icon" href="data:,">
|
||||
<script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
|
||||
|
||||
<title>{% block title %}{% endblock %}</title>
|
||||
</head>
|
||||
<body>
|
||||
{% include 'navbar.html' %}
|
||||
|
||||
<div class="container">
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user