246 lines
11 KiB
PHP
246 lines
11 KiB
PHP
<?php
|
|
session_start();
|
|
if (!isset($_SESSION['user_id'])) {
|
|
header('Location: login.php');
|
|
exit;
|
|
}
|
|
|
|
require_once 'db/config.php';
|
|
require_once 'utils.php';
|
|
|
|
$user_id = $_SESSION['user_id'];
|
|
$p_user = get_user_by_id($user_id);
|
|
$servers = get_user_servers($user_id);
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Discord V2</title>
|
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
</head>
|
|
<body>
|
|
<div class="app-container">
|
|
<!-- Servers List -->
|
|
<div class="servers-list">
|
|
<?php foreach ($servers as $server): ?>
|
|
<div class="server-icon" data-server-id="<?php echo $server['id']; ?>" title="<?php echo htmlspecialchars($server['name']); ?>">
|
|
<?php echo htmlspecialchars(strtoupper(substr($server['name'], 0, 1))); ?>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<a href="create_server.php" class="server-icon add-server-btn" title="Ajouter un serveur">+</a>
|
|
</div>
|
|
|
|
<!-- Sidebar (Channels & User Panel) -->
|
|
<div class="sidebar">
|
|
<div class="sidebar-header">
|
|
<h2 id="server-name">Sélectionnez un serveur</h2>
|
|
</div>
|
|
<div class="channels-list" id="channels-list">
|
|
<!-- Les canaux seront injectés ici par JS -->
|
|
</div>
|
|
<div class="user-panel">
|
|
<div class="user-info">
|
|
<div class="user-avatar"></div>
|
|
<span class="user-name"><?php echo htmlspecialchars($p_user['username']); ?></span>
|
|
</div>
|
|
<a href="logout.php" class="logout-btn" title="Déconnexion">
|
|
<svg width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M16 17v-3H9v-4h7V7l5 5-5 5zm-8-4H0v4h8v-4zm0-4H0v4h8V9zm0-4H0v4h8V5z"></path></svg>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chat Area -->
|
|
<div class="chat-container">
|
|
<div class="chat-header">
|
|
<span id="channel-name"></span>
|
|
</div>
|
|
<div class="messages-list" id="messages-list">
|
|
<!-- Les messages seront injectés ici -->
|
|
<div style="text-align: center; color: var(--text-muted); margin-top: 20px;">
|
|
Sélectionnez un canal pour commencer à discuter.
|
|
</div>
|
|
</div>
|
|
<form class="chat-input-form" id="message-form" style="display: none;">
|
|
<input type="hidden" id="active-channel-id" name="channel_id">
|
|
<input type="text" id="message-input" name="message" class="chat-input" placeholder="Envoyer un message...">
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
const servers = document.querySelectorAll('.server-icon[data-server-id]');
|
|
const serverNameEl = document.getElementById('server-name');
|
|
const channelsListEl = document.getElementById('channels-list');
|
|
const channelNameEl = document.getElementById('channel-name');
|
|
const messagesListEl = document.getElementById('messages-list');
|
|
const messageForm = document.getElementById('message-form');
|
|
const messageInput = document.getElementById('message-input');
|
|
const activeChannelIdInput = document.getElementById('active-channel-id');
|
|
|
|
let activeServerId = null;
|
|
let activeChannelId = null;
|
|
let messagePollingInterval = null;
|
|
|
|
servers.forEach(server => {
|
|
server.addEventListener('click', function() {
|
|
const serverId = this.dataset.serverId;
|
|
if (serverId === activeServerId) return;
|
|
|
|
servers.forEach(s => s.classList.remove('active'));
|
|
this.classList.add('active');
|
|
|
|
activeServerId = serverId;
|
|
activeChannelId = null;
|
|
if (messagePollingInterval) {
|
|
clearInterval(messagePollingInterval);
|
|
messagePollingInterval = null;
|
|
}
|
|
|
|
serverNameEl.textContent = 'Chargement...';
|
|
channelsListEl.innerHTML = '';
|
|
messagesListEl.innerHTML = '<div style="text-align: center; color: var(--text-muted); margin-top: 20px;">Sélectionnez un canal.</div>';
|
|
channelNameEl.textContent = '';
|
|
messageForm.style.display = 'none';
|
|
|
|
fetch(`get_channels.php?server_id=${serverId}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.error) {
|
|
serverNameEl.textContent = 'Erreur';
|
|
channelsListEl.innerHTML = `<p style="color: #f04747;">${data.error}</p>`;
|
|
return;
|
|
}
|
|
|
|
serverNameEl.textContent = data.server_name;
|
|
channelsListEl.innerHTML = '';
|
|
if (data.channels.length > 0) {
|
|
data.channels.forEach(channel => {
|
|
const channelEl = document.createElement('div');
|
|
channelEl.classList.add('channel');
|
|
channelEl.dataset.channelId = channel.id;
|
|
channelEl.textContent = channel.name;
|
|
channelEl.addEventListener('click', () => selectChannel(channel.id, channel.name));
|
|
channelsListEl.appendChild(channelEl);
|
|
});
|
|
selectChannel(data.channels[0].id, data.channels[0].name);
|
|
} else {
|
|
channelsListEl.innerHTML = '<p style="color: var(--text-muted); padding: 0 16px;">Aucun canal trouvé.</p>';
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error fetching channels:', error);
|
|
serverNameEl.textContent = 'Erreur de connexion';
|
|
});
|
|
});
|
|
});
|
|
|
|
function selectChannel(channelId, channelName) {
|
|
if (channelId === activeChannelId) return;
|
|
activeChannelId = channelId;
|
|
|
|
if (messagePollingInterval) {
|
|
clearInterval(messagePollingInterval);
|
|
}
|
|
|
|
document.querySelectorAll('.channel').forEach(c => {
|
|
c.classList.toggle('active', c.dataset.channelId === channelId.toString());
|
|
});
|
|
|
|
channelNameEl.textContent = channelName;
|
|
messagesListEl.innerHTML = '<p style="text-align:center; color: var(--text-muted);">Chargement des messages...</p>';
|
|
messageForm.style.display = 'block';
|
|
activeChannelIdInput.value = channelId;
|
|
messageInput.value = '';
|
|
messageInput.focus();
|
|
|
|
fetchMessages(channelId);
|
|
messagePollingInterval = setInterval(() => fetchMessages(channelId), 3000);
|
|
}
|
|
|
|
function fetchMessages(channelId) {
|
|
const wasScrolledToBottom = messagesListEl.scrollHeight - messagesListEl.clientHeight <= messagesListEl.scrollTop + 1;
|
|
|
|
fetch(`get_messages.php?channel_id=${channelId}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
let newHTML = '';
|
|
if (data.error) {
|
|
newHTML = `<p style="color: #f04747; text-align:center;">${data.error}</p>`;
|
|
} else if (data.length > 0) {
|
|
data.forEach(msg => {
|
|
newHTML += `
|
|
<div class="message">
|
|
<div class="message-avatar"></div>
|
|
<div class="message-content">
|
|
<span class="message-author">${escapeHTML(msg.username)}</span>
|
|
<div class="message-text">${escapeHTML(msg.message)}</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
});
|
|
} else {
|
|
newHTML = '<p style="text-align:center; color: var(--text-muted);">Aucun message. Soyez le premier à en envoyer un !</p>';
|
|
}
|
|
|
|
if (messagesListEl.innerHTML !== newHTML) {
|
|
messagesListEl.innerHTML = newHTML;
|
|
if (wasScrolledToBottom) {
|
|
messagesListEl.scrollTop = messagesListEl.scrollHeight;
|
|
}
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error fetching messages:', error);
|
|
// Avoid replacing content on intermittent network errors during polling
|
|
if (messagesListEl.innerHTML.includes('Chargement des messages...')) {
|
|
messagesListEl.innerHTML = '<p style="color: #f04747; text-align:center;">Erreur de chargement des messages.</p>';
|
|
}
|
|
});
|
|
}
|
|
|
|
messageForm.addEventListener('submit', function(e) {
|
|
e.preventDefault();
|
|
const message = messageInput.value.trim();
|
|
if (!message || !activeChannelId) return;
|
|
|
|
const formData = new FormData();
|
|
formData.append('channel_id', activeChannelId);
|
|
formData.append('message', message);
|
|
|
|
fetch('send_message.php', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
messageInput.value = '';
|
|
fetchMessages(activeChannelId); // Refresh messages immediately
|
|
} else {
|
|
alert('Erreur lors de l'envoi du message: ' + data.error);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error sending message:', error);
|
|
alert('Erreur réseau.');
|
|
});
|
|
});
|
|
|
|
function escapeHTML(str) {
|
|
return str.replace(/[&<>"']/g, function(match) {
|
|
return {
|
|
'&': '&',
|
|
'<': '<',
|
|
'>': '>',
|
|
'"': '"',
|
|
"'": '''
|
|
}[match];
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|