-
Gebruik deze commando's tijdens het chatten om extra acties uit te voeren.
+
Use these commands while chatting to perform additional actions.
- | Commando | Beschrijving |
+ | Command | Description |
| /add <username> |
- Voeg een gebruiker toe aan de huidige chat |
+ Add a user to the current chat |
| /break |
- Verlaat de huidige chat en ga terug naar chat selectie |
+ Leave the current chat and return to chat selection |
| /quit |
- Sluit het programma volledig af en verbreek de verbinding |
+ Close the program completely and disconnect |
@@ -613,46 +628,46 @@
-
// architectuur
-
Hoe het werkt
-
Terminal Chat gebruikt een klassiek client-server model met TCP-sockets voor betrouwbare, bidirectionele communicatie.
+
// architecture
+
How it works
+
Terminal Chat uses a classic client-server model with TCP sockets for reliable, bidirectional communication.
Client
- Python script dat verbinding maakt met de server. Verwerkt input/output en toont berichten met ANSI kleuren.
+ Python script that connects to the server. Handles input/output and displays messages with ANSI colors.
↓ TCP Socket ↓
Server
- Draait centraal en beheert alle verbindingen, authenticatie, chatkanalen en bericht routing.
+ Runs centrally and manages all connections, authentication, chat channels, and message routing.
↓ Threading ↓
- Opslag
- Gebruikers en chatgegevens worden server-side opgeslagen. Elke client krijgt een eigen thread voor non-blocking I/O.
+ Storage
+ User and chat data are stored server-side. Each client gets its own thread for non-blocking I/O.
- # Vereenvoudigd overzicht
- client.py → Verbindt met server via socket
+ # Simplified overview
+ client.py → Connects to server via socket
→ Login / Signup prompt
- → Chat selectie menu
- → Berichten versturen & ontvangen
- server.py → Luistert op TCP poort
- → Nieuwe thread per client
- → Authenticatie afhandeling
- → Bericht broadcast naar kanaal
+ → Chat selection menu
+ → Send & receive messages
+ server.py → Listens on TCP port
+ → New thread per client
+ → Authentication handling
+ → Message broadcast to channel
@@ -683,21 +698,156 @@
}
// === TERMINAL ANIMATION ===
+ const chatMessages = [
+ { user: 'alice', color: '#06b6d4', text: 'hey everyone, server is up', align: 'left' },
+ { user: 'jake', color: '#f97316', text: 'nice, just connected', align: 'left' },
+ { user: 'alice', color: '#06b6d4', text: 'max you there?', align: 'left' },
+ { user: 'max', color: '#eab308', text: 'yeah just logged in', align: 'right' },
+ { user: 'jake', color: '#f97316', text: 'this thing is actually fast', align: 'left' },
+ { user: 'max', color: '#eab308', text: 'right? tcp sockets go crazy', align: 'right' },
+ { user: 'alice', color: '#06b6d4', text: 'lol true. let me add sarah', align: 'left' },
+ { user: 'alice', color: '#06b6d4', text: '/add sarah', align: 'left', isCmd: true },
+ { user: null, color: '#22c55e', text: 'sarah has been added to the chat.', align: 'center', isSystem: true },
+ { user: 'sarah', color: '#a78bfa', text: 'heyy thanks for the invite', align: 'left' },
+ { user: 'max', color: '#eab308', text: 'welcome! we were just testing', align: 'right' },
+ { user: 'sarah', color: '#a78bfa', text: 'looks super clean ngl', align: 'left' },
+ { user: 'jake', color: '#f97316', text: 'agreed, terminal chat supremacy', align: 'left' },
+ { user: 'max', color: '#eab308', text: 'haha lets gooo', align: 'right' },
+ ];
+
+ let typingMsg = 'who else should we add?';
+
function animateTerminal() {
- const lines = document.querySelectorAll('.terminal-line');
+ const termBody = document.getElementById('terminalBody');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
- lines.forEach(line => {
- const delay = parseInt(line.getAttribute('data-delay')) || 0;
- setTimeout(() => line.classList.add('visible'), delay);
- });
+ startLoginPhase();
observer.unobserve(entry.target);
}
});
}, { threshold: 0.3 });
- observer.observe(document.getElementById('terminalBody'));
+ observer.observe(termBody);
}
+
+ function startLoginPhase() {
+ const lines = document.querySelectorAll('#loginPhase .terminal-line');
+ lines.forEach(line => {
+ const delay = parseInt(line.getAttribute('data-delay')) || 0;
+ setTimeout(() => line.classList.add('visible'), delay);
+ });
+
+ // After login flow finishes, transition to chat
+ const lastDelay = Math.max(...Array.from(lines).map(l => parseInt(l.getAttribute('data-delay')) || 0));
+ setTimeout(() => {
+ transitionToChat();
+ }, lastDelay + 800);
+ }
+
+ function transitionToChat() {
+ const loginPhase = document.getElementById('loginPhase');
+ const chatPhase = document.getElementById('chatPhase');
+
+ loginPhase.style.transition = 'opacity 0.4s';
+ loginPhase.style.opacity = '0';
+
+ setTimeout(() => {
+ loginPhase.style.display = 'none';
+ chatPhase.style.display = 'flex';
+
+ // Show green line and input area
+ setTimeout(() => {
+ document.getElementById('greenLine').style.opacity = '1';
+ document.getElementById('inputArea').style.opacity = '1';
+ }, 300);
+
+ // Start adding messages one by one
+ let msgIndex = 0;
+ const msgContainer = document.getElementById('chatMessages');
+ const typingEl = document.getElementById('typingText');
+
+ function typeInInput(text, callback) {
+ typingEl.textContent = '';
+ let i = 0;
+ function typeChar() {
+ if (i < text.length) {
+ typingEl.textContent += text[i];
+ i++;
+ setTimeout(typeChar, 45 + Math.random() * 60);
+ } else {
+ // Brief pause then "send"
+ setTimeout(() => {
+ typingEl.textContent = '';
+ callback();
+ }, 350);
+ }
+ }
+ typeChar();
+ }
+
+ function appendMessage(msg) {
+ const div = document.createElement('div');
+ div.style.opacity = '0';
+ div.style.transform = 'translateY(4px)';
+ div.style.transition = 'all 0.3s ease';
+
+ if (msg.isSystem) {
+ div.style.textAlign = 'center';
+ div.innerHTML = '
' + msg.text + '';
+ } else if (msg.align === 'right') {
+ div.style.textAlign = 'right';
+ div.innerHTML = '
[' + msg.user + '] ' + (msg.isCmd ? '
' + msg.text + '' : msg.text);
+ } else {
+ div.style.textAlign = 'left';
+ div.innerHTML = '
[' + msg.user + '] ' + (msg.isCmd ? '
' + msg.text + '' : msg.text);
+ }
+
+ msgContainer.appendChild(div);
+ requestAnimationFrame(() => {
+ requestAnimationFrame(() => {
+ div.style.opacity = '1';
+ div.style.transform = 'translateY(0)';
+ });
+ });
+ }
+
+ function addNextMessage() {
+ if (msgIndex >= chatMessages.length) {
+ // Final typing animation (no send)
+ setTimeout(() => {
+ let i = 0;
+ function lastType() {
+ if (i < typingMsg.length) {
+ typingEl.textContent += typingMsg[i];
+ i++;
+ setTimeout(lastType, 60 + Math.random() * 80);
+ }
+ }
+ lastType();
+ }, 400);
+ return;
+ }
+
+ const msg = chatMessages[msgIndex];
+ msgIndex++;
+
+ if (msg.user === 'max') {
+ // Max's messages: type in input first, then send to chat
+ typeInInput(msg.text, () => {
+ appendMessage(msg);
+ setTimeout(addNextMessage, 400 + Math.random() * 400);
+ });
+ } else {
+ // Other users: just appear after a delay
+ appendMessage(msg);
+ setTimeout(addNextMessage, 600 + Math.random() * 500);
+ }
+ }
+
+ setTimeout(addNextMessage, 500);
+ }, 400);
+ }
+
animateTerminal();
// === FADE-IN SECTIONS ===