v1
This commit is contained in:
parent
f961943621
commit
2642f97c8b
35
api_v1_messages.php
Normal file
35
api_v1_messages.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
header('Content-Type: application/json');
|
||||
require_once 'db/config.php';
|
||||
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$content = $data['content'] ?? '';
|
||||
$channel_id = (int)($data['channel_id'] ?? 1);
|
||||
$user_id = 1; // Mock logged in user
|
||||
|
||||
if (empty($content)) {
|
||||
echo json_encode(['success' => false, 'error' => 'Empty content']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = db()->prepare("INSERT INTO messages (channel_id, user_id, content) VALUES (?, ?, ?)");
|
||||
$stmt->execute([$channel_id, $user_id, $content]);
|
||||
$last_id = db()->lastInsertId();
|
||||
|
||||
// Fetch message with username for the response
|
||||
$stmt = db()->prepare("SELECT m.*, u.username FROM messages m JOIN users u ON m.user_id = u.id WHERE m.id = ?");
|
||||
$stmt->execute([$last_id]);
|
||||
$msg = $stmt->fetch();
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => [
|
||||
'username' => $msg['username'],
|
||||
'content' => htmlspecialchars($msg['content']),
|
||||
'time' => date('H:i', strtotime($msg['created_at']))
|
||||
]
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
|
||||
}
|
||||
213
assets/css/discord.css
Normal file
213
assets/css/discord.css
Normal file
@ -0,0 +1,213 @@
|
||||
:root {
|
||||
--bg-servers: #1e1f22;
|
||||
--bg-channels: #2b2d31;
|
||||
--bg-chat: #313338;
|
||||
--bg-members: #2b2d31;
|
||||
--text-primary: #dbdee1;
|
||||
--text-muted: #949ba4;
|
||||
--blurple: #5865f2;
|
||||
--hover: #35373c;
|
||||
--active: #3f4147;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Inter', system-ui, -apple-system, sans-serif;
|
||||
background-color: var(--bg-servers);
|
||||
color: var(--text-primary);
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.discord-app {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
/* Servers Sidebar */
|
||||
.servers-sidebar {
|
||||
width: 72px;
|
||||
background-color: var(--bg-servers);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 12px 0;
|
||||
gap: 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.server-icon {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
background-color: var(--bg-chat);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
color: var(--text-primary);
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.server-icon:hover {
|
||||
border-radius: 16px;
|
||||
background-color: var(--blurple);
|
||||
}
|
||||
|
||||
.server-icon.active {
|
||||
border-radius: 16px;
|
||||
background-color: var(--blurple);
|
||||
}
|
||||
|
||||
/* Channels Sidebar */
|
||||
.channels-sidebar {
|
||||
width: 240px;
|
||||
background-color: var(--bg-channels);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.channels-header {
|
||||
height: 48px;
|
||||
padding: 0 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-shadow: 0 1px 0 rgba(0,0,0,0.2);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.channels-list {
|
||||
flex: 1;
|
||||
padding: 8px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.channel-item {
|
||||
padding: 6px 8px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
color: var(--text-muted);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 2px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.channel-item:hover {
|
||||
background-color: var(--hover);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.channel-item.active {
|
||||
background-color: var(--active);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.channel-item::before {
|
||||
content: "#";
|
||||
font-size: 1.2em;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
/* Chat Area */
|
||||
.chat-container {
|
||||
flex: 1;
|
||||
background-color: var(--bg-chat);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.chat-header {
|
||||
height: 48px;
|
||||
padding: 0 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
box-shadow: 0 1px 0 rgba(0,0,0,0.2);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.messages-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.message-item {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.message-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: #4e5058;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.message-author {
|
||||
font-weight: bold;
|
||||
font-size: 0.95em;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.message-text {
|
||||
font-size: 0.95em;
|
||||
line-height: 1.4;
|
||||
color: #dbdee1;
|
||||
}
|
||||
|
||||
.message-time {
|
||||
font-size: 0.75em;
|
||||
color: var(--text-muted);
|
||||
margin-left: 8px;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* Input Area */
|
||||
.chat-input-container {
|
||||
padding: 0 16px 24px 16px;
|
||||
}
|
||||
|
||||
.chat-input-wrapper {
|
||||
background-color: #383a40;
|
||||
border-radius: 8px;
|
||||
padding: 11px 16px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.chat-input {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: var(--text-primary);
|
||||
width: 100%;
|
||||
outline: none;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Members Sidebar */
|
||||
.members-sidebar {
|
||||
width: 240px;
|
||||
background-color: var(--bg-members);
|
||||
padding: 24px 8px;
|
||||
display: none; /* Hidden on mobile/small screens */
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.members-sidebar {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
55
assets/js/main.js
Normal file
55
assets/js/main.js
Normal file
@ -0,0 +1,55 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const chatForm = document.getElementById('chat-form');
|
||||
const chatInput = document.getElementById('chat-input');
|
||||
const messagesList = document.getElementById('messages-list');
|
||||
|
||||
// Scroll to bottom
|
||||
messagesList.scrollTop = messagesList.scrollHeight;
|
||||
|
||||
chatForm.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
const content = chatInput.value.trim();
|
||||
if (!content) return;
|
||||
|
||||
chatInput.value = '';
|
||||
|
||||
try {
|
||||
const response = await fetch('api_v1_messages.php', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
content: content,
|
||||
channel_id: new URLSearchParams(window.location.search).get('channel_id') || 1
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
appendMessage(result.message);
|
||||
messagesList.scrollTop = messagesList.scrollHeight;
|
||||
} else {
|
||||
alert('Error: ' + result.error);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to send message:', err);
|
||||
}
|
||||
});
|
||||
|
||||
function appendMessage(msg) {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'message-item';
|
||||
div.innerHTML = `
|
||||
<div class="message-avatar"></div>
|
||||
<div class="message-content">
|
||||
<div class="message-author">
|
||||
${msg.username}
|
||||
<span class="message-time">${msg.time}</span>
|
||||
</div>
|
||||
<div class="message-text">
|
||||
${msg.content.replace(/\n/g, '<br>')}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
messagesList.appendChild(div);
|
||||
}
|
||||
});
|
||||
50
database/schema.sql
Normal file
50
database/schema.sql
Normal file
@ -0,0 +1,50 @@
|
||||
-- Initial schema for Discord-like app
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
email VARCHAR(100) NOT NULL UNIQUE,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
avatar_url VARCHAR(255),
|
||||
status VARCHAR(20) DEFAULT 'offline',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS servers (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
owner_id INT NOT NULL,
|
||||
icon_url VARCHAR(255),
|
||||
invite_code VARCHAR(10) UNIQUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (owner_id) REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS channels (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
server_id INT NOT NULL,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
type ENUM('text', 'voice') DEFAULT 'text',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (server_id) REFERENCES servers(id) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
channel_id INT NOT NULL,
|
||||
user_id INT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (channel_id) REFERENCES channels(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
);
|
||||
|
||||
-- Seed initial data
|
||||
INSERT IGNORE INTO users (id, username, email, password_hash, status) VALUES
|
||||
(1, 'System', 'system@local', '$2y$10$xyz', 'online');
|
||||
|
||||
INSERT IGNORE INTO servers (id, name, owner_id, invite_code) VALUES
|
||||
(1, 'General Community', 1, 'GEN-123');
|
||||
|
||||
INSERT IGNORE INTO channels (id, server_id, name) VALUES
|
||||
(1, 1, 'general'),
|
||||
(2, 1, 'random');
|
||||
10
db_init.php
Normal file
10
db_init.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
require_once 'db/config.php';
|
||||
|
||||
try {
|
||||
$sql = file_get_contents('database/schema.sql');
|
||||
db()->exec($sql);
|
||||
echo "Database initialized successfully.\n";
|
||||
} catch (Exception $e) {
|
||||
echo "Error initializing database: " . $e->getMessage() . "\n";
|
||||
}
|
||||
274
index.php
274
index.php
@ -1,150 +1,142 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
@ini_set('display_errors', '1');
|
||||
@error_reporting(E_ALL);
|
||||
@date_default_timezone_set('UTC');
|
||||
require_once 'db/config.php';
|
||||
|
||||
$phpVersion = PHP_VERSION;
|
||||
$now = date('Y-m-d H:i:s');
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>New Style</title>
|
||||
<?php
|
||||
// Read project preview data from environment
|
||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
||||
// Simple session check (mock for now, assume User 1)
|
||||
$current_user_id = 1;
|
||||
|
||||
// Fetch servers
|
||||
$servers = db()->query("SELECT * FROM servers LIMIT 10")->fetchAll();
|
||||
$active_server_id = $_GET['server_id'] ?? ($servers[0]['id'] ?? 1);
|
||||
|
||||
// Fetch channels
|
||||
$stmt = db()->prepare("SELECT * FROM channels WHERE server_id = ?");
|
||||
$stmt->execute([$active_server_id]);
|
||||
$channels = $stmt->fetchAll();
|
||||
$active_channel_id = $_GET['channel_id'] ?? ($channels[0]['id'] ?? 1);
|
||||
|
||||
// Fetch messages
|
||||
$stmt = db()->prepare("
|
||||
SELECT m.*, u.username, u.avatar_url
|
||||
FROM messages m
|
||||
JOIN users u ON m.user_id = u.id
|
||||
WHERE m.channel_id = ?
|
||||
ORDER BY m.created_at ASC
|
||||
LIMIT 50
|
||||
");
|
||||
$stmt->execute([$active_channel_id]);
|
||||
$messages = $stmt->fetchAll();
|
||||
|
||||
$current_channel_name = 'general';
|
||||
foreach($channels as $c) if($c['id'] == $active_channel_id) $current_channel_name = $c['name'];
|
||||
|
||||
// SEO & Env tags
|
||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Discord-like messaging app built with PHP';
|
||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
?>
|
||||
<?php if ($projectDescription): ?>
|
||||
<!-- Meta description -->
|
||||
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
||||
<!-- Open Graph meta tags -->
|
||||
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<!-- Twitter meta tags -->
|
||||
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<?php endif; ?>
|
||||
<?php if ($projectImageUrl): ?>
|
||||
<!-- Open Graph image -->
|
||||
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<!-- Twitter image -->
|
||||
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<?php endif; ?>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-color-start: #6a11cb;
|
||||
--bg-color-end: #2575fc;
|
||||
--text-color: #ffffff;
|
||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
||||
animation: bg-pan 20s linear infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
@keyframes bg-pan {
|
||||
0% { background-position: 0% 0%; }
|
||||
100% { background-position: 100% 100%; }
|
||||
}
|
||||
main {
|
||||
padding: 2rem;
|
||||
}
|
||||
.card {
|
||||
background: var(--card-bg-color);
|
||||
border: 1px solid var(--card-border-color);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.loader {
|
||||
margin: 1.25rem auto 1.25rem;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
||||
border-top-color: #fff;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
.hint {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px; height: 1px;
|
||||
padding: 0; margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap; border: 0;
|
||||
}
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 1rem;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
p {
|
||||
margin: 0.5rem 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
code {
|
||||
background: rgba(0,0,0,0.2);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
}
|
||||
footer {
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>#<?php echo htmlspecialchars($current_channel_name); ?> | <?php echo htmlspecialchars($projectDescription); ?></title>
|
||||
|
||||
<meta name="description" content="<?php echo htmlspecialchars($projectDescription); ?>">
|
||||
<meta property="og:description" content="<?php echo htmlspecialchars($projectDescription); ?>">
|
||||
<meta property="twitter:description" content="<?php echo htmlspecialchars($projectDescription); ?>">
|
||||
<?php if ($projectImageUrl): ?>
|
||||
<meta property="og:image" content="<?php echo htmlspecialchars($projectImageUrl); ?>">
|
||||
<meta property="twitter:image" content="<?php echo htmlspecialchars($projectImageUrl); ?>">
|
||||
<?php endif; ?>
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/discord.css?v=<?php echo time(); ?>">
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="card">
|
||||
<h1>Analyzing your requirements and generating your website…</h1>
|
||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||
<span class="sr-only">Loading…</span>
|
||||
</div>
|
||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
||||
|
||||
<div class="discord-app">
|
||||
<!-- Servers Sidebar -->
|
||||
<div class="servers-sidebar">
|
||||
<a href="index.php" class="server-icon active" title="Home">
|
||||
<svg width="28" height="20" viewBox="0 0 28 20" fill="currentColor"><path d="M23.0212 1.67671C21.3107 0.883335 19.4805 0.314845 17.5566 0C17.3137 0.434033 17.0423 1.00252 16.8488 1.46581C14.8193 1.16016 12.8016 1.16016 10.8011 1.46581C10.6076 1.00252 10.3255 0.434033 10.0827 0C8.14811 0.314845 6.31792 0.883335 4.60741 1.67671C1.14775 6.84711 0.210418 11.8962 0.67293 16.8681C2.9723 18.5677 5.19143 19.5997 7.37191 20C7.91578 19.2558 8.3897 18.4616 8.79155 17.6166C7.99616 17.3148 7.2343 16.9416 6.51603 16.505C6.70881 16.3639 6.89745 16.2125 7.07923 16.052C11.4116 18.0494 16.1264 18.0494 20.4137 16.052C20.597 16.2125 20.7856 16.3639 20.9784 16.505C20.2586 16.9416 19.4967 17.3148 18.7013 17.6166C19.1031 18.4616 19.577 19.2558 20.1209 20C22.3014 19.5997 24.5205 18.5677 26.8199 16.8681C27.3693 11.127 25.9189 6.13063 23.0212 1.67671ZM9.51636 13.6749C8.21405 13.6749 7.14188 12.4839 7.14188 11.026C7.14188 9.56816 8.19284 8.3771 9.51636 8.3771C10.8399 8.3771 11.912 9.56816 11.8908 11.026C11.8908 12.4839 10.8399 13.6749 9.51636 13.6749ZM18.0051 13.6749C16.7028 13.6749 15.6306 12.4839 15.6306 11.026C15.6306 9.56816 16.6815 8.3771 18.0051 8.3771C19.3286 8.3771 20.4008 9.56816 20.3796 11.026C20.3796 12.4839 19.3286 13.6749 18.0051 13.6749Z"/></svg>
|
||||
</a>
|
||||
<hr style="width: 32px; border-color: #35363c; margin: 4px 0;">
|
||||
<?php foreach($servers as $s): ?>
|
||||
<a href="?server_id=<?php echo $s['id']; ?>"
|
||||
class="server-icon <?php echo $s['id'] == $active_server_id ? 'active' : ''; ?>"
|
||||
title="<?php echo htmlspecialchars($s['name']); ?>">
|
||||
<?php echo mb_substr($s['name'], 0, 1); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||
</footer>
|
||||
|
||||
<!-- Channels Sidebar -->
|
||||
<div class="channels-sidebar">
|
||||
<div class="channels-header">
|
||||
<?php echo htmlspecialchars($servers[0]['name'] ?? 'Server'); ?>
|
||||
</div>
|
||||
<div class="channels-list">
|
||||
<div style="color: var(--text-muted); font-size: 0.75em; text-transform: uppercase; font-weight: bold; margin-bottom: 8px; padding-left: 8px;">
|
||||
Text Channels
|
||||
</div>
|
||||
<?php foreach($channels as $c): ?>
|
||||
<a href="?server_id=<?php echo $active_server_id; ?>&channel_id=<?php echo $c['id']; ?>"
|
||||
class="channel-item <?php echo $c['id'] == $active_channel_id ? 'active' : ''; ?>">
|
||||
<?php echo htmlspecialchars($c['name']); ?>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Chat Area -->
|
||||
<div class="chat-container">
|
||||
<div class="chat-header">
|
||||
<span style="color: var(--text-muted); margin-right: 8px;">#</span>
|
||||
<?php echo htmlspecialchars($current_channel_name); ?>
|
||||
</div>
|
||||
<div class="messages-list" id="messages-list">
|
||||
<?php if(empty($messages)): ?>
|
||||
<div style="text-align: center; color: var(--text-muted); margin-top: 40px;">
|
||||
<h4>Welcome to #<?php echo htmlspecialchars($current_channel_name); ?>!</h4>
|
||||
<p>This is the start of the #<?php echo htmlspecialchars($current_channel_name); ?> channel.</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php foreach($messages as $m): ?>
|
||||
<div class="message-item">
|
||||
<div class="message-avatar"></div>
|
||||
<div class="message-content">
|
||||
<div class="message-author">
|
||||
<?php echo htmlspecialchars($m['username']); ?>
|
||||
<span class="message-time"><?php echo date('H:i', strtotime($m['created_at'])); ?></span>
|
||||
</div>
|
||||
<div class="message-text">
|
||||
<?php echo nl2br(htmlspecialchars($m['content'])); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<div class="chat-input-container">
|
||||
<form id="chat-form">
|
||||
<div class="chat-input-wrapper">
|
||||
<input type="text" id="chat-input" class="chat-input" placeholder="Message #<?php echo htmlspecialchars($current_channel_name); ?>" autocomplete="off">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Members Sidebar -->
|
||||
<div class="members-sidebar">
|
||||
<div style="color: var(--text-muted); font-size: 0.75em; text-transform: uppercase; font-weight: bold; margin-bottom: 8px;">
|
||||
Online — 1
|
||||
</div>
|
||||
<div class="channel-item" style="color: var(--text-primary);">
|
||||
<div class="message-avatar" style="width: 32px; height: 32px; background-color: #23a559;"></div>
|
||||
System
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user