v3
This commit is contained in:
parent
4883125cda
commit
ef520f4259
31
api_v1_channels.php
Normal file
31
api_v1_channels.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
require_once 'auth/session.php';
|
||||||
|
requireLogin();
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$server_id = $_POST['server_id'] ?? 0;
|
||||||
|
$name = $_POST['name'] ?? '';
|
||||||
|
$type = $_POST['type'] ?? 'text';
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
// Check if user is owner of the server or has permissions (simplified check for now: user must be a member)
|
||||||
|
$stmt = db()->prepare("SELECT 1 FROM server_members WHERE server_id = ? AND user_id = ?");
|
||||||
|
$stmt->execute([$server_id, $user_id]);
|
||||||
|
|
||||||
|
if ($stmt->fetch() && $name) {
|
||||||
|
try {
|
||||||
|
// Basic sanitization for channel name
|
||||||
|
$name = strtolower(preg_replace('/[^a-zA-Z0-3\-]/', '-', $name));
|
||||||
|
|
||||||
|
$stmt = db()->prepare("INSERT INTO channels (server_id, name, type) VALUES (?, ?, ?)");
|
||||||
|
$stmt->execute([$server_id, $name, $type]);
|
||||||
|
$channel_id = db()->lastInsertId();
|
||||||
|
|
||||||
|
header('Location: index.php?server_id=' . $server_id . '&channel_id=' . $channel_id);
|
||||||
|
exit;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
die("Error creating channel: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
header('Location: index.php');
|
||||||
55
api_v1_servers.php
Normal file
55
api_v1_servers.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
require_once 'auth/session.php';
|
||||||
|
requireLogin();
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$action = $_POST['action'] ?? 'create';
|
||||||
|
$user_id = $_SESSION['user_id'];
|
||||||
|
|
||||||
|
if ($action === 'join') {
|
||||||
|
$invite_code = $_POST['invite_code'] ?? '';
|
||||||
|
$stmt = db()->prepare("SELECT id FROM servers WHERE invite_code = ?");
|
||||||
|
$stmt->execute([$invite_code]);
|
||||||
|
$server = $stmt->fetch();
|
||||||
|
|
||||||
|
if ($server) {
|
||||||
|
$stmt = db()->prepare("INSERT IGNORE INTO server_members (server_id, user_id) VALUES (?, ?)");
|
||||||
|
$stmt->execute([$server['id'], $user_id]);
|
||||||
|
header('Location: index.php?server_id=' . $server['id']);
|
||||||
|
exit;
|
||||||
|
} else {
|
||||||
|
die("Invalid invite code.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = $_POST['name'] ?? '';
|
||||||
|
|
||||||
|
if ($name) {
|
||||||
|
try {
|
||||||
|
$db = db();
|
||||||
|
$db->beginTransaction();
|
||||||
|
|
||||||
|
// Create server
|
||||||
|
$invite_code = substr(strtoupper(md5(uniqid())), 0, 8);
|
||||||
|
$stmt = $db->prepare("INSERT INTO servers (name, owner_id, invite_code) VALUES (?, ?, ?)");
|
||||||
|
$stmt->execute([$name, $user_id, $invite_code]);
|
||||||
|
$server_id = $db->lastInsertId();
|
||||||
|
|
||||||
|
// Add owner as member
|
||||||
|
$stmt = $db->prepare("INSERT INTO server_members (server_id, user_id) VALUES (?, ?)");
|
||||||
|
$stmt->execute([$server_id, $user_id]);
|
||||||
|
|
||||||
|
// Create default channel
|
||||||
|
$stmt = $db->prepare("INSERT INTO channels (server_id, name, type) VALUES (?, 'general', 'text')");
|
||||||
|
$stmt->execute([$server_id]);
|
||||||
|
|
||||||
|
$db->commit();
|
||||||
|
header('Location: index.php?server_id=' . $server_id);
|
||||||
|
exit;
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$db->rollBack();
|
||||||
|
die("Error creating server: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
header('Location: index.php');
|
||||||
@ -120,6 +120,15 @@ body {
|
|||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.server-icon.add-btn {
|
||||||
|
color: #23a559;
|
||||||
|
}
|
||||||
|
|
||||||
|
.server-icon.add-btn:hover {
|
||||||
|
background-color: #23a559;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
.channel-category {
|
.channel-category {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
@ -127,6 +136,46 @@ body {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-channel-btn {
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin-right: 8px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-channel-btn:hover {
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modals */
|
||||||
|
.modal-content {
|
||||||
|
background-color: var(--bg-channels);
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
border-bottom: 1px solid var(--bg-servers);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-footer {
|
||||||
|
border-top: 1px solid var(--bg-servers);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
background-color: var(--bg-servers);
|
||||||
|
border: none;
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control:focus {
|
||||||
|
background-color: var(--bg-servers);
|
||||||
|
color: var(--text-primary);
|
||||||
|
box-shadow: 0 0 0 0.25rem rgba(88, 101, 242, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* User Panel */
|
/* User Panel */
|
||||||
|
|||||||
@ -43,6 +43,32 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
content: content,
|
content: content,
|
||||||
channel_id: channel_id
|
channel_id: channel_id
|
||||||
})
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
if (result.success) {
|
||||||
|
// If WS is connected, we might want to let WS handle the UI update
|
||||||
|
// But for simplicity, we append here and also send to WS
|
||||||
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: 'message',
|
||||||
|
data: JSON.stringify({
|
||||||
|
...result.message,
|
||||||
|
channel_id: channel_id
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
appendMessage(result.message);
|
||||||
|
messagesList.scrollTop = messagesList.scrollHeight;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert('Error: ' + result.error);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to send message:', err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Voice
|
// Voice
|
||||||
const voiceHandler = new VoiceChannel(ws);
|
const voiceHandler = new VoiceChannel(ws);
|
||||||
document.querySelectorAll('.voice-item').forEach(item => {
|
document.querySelectorAll('.voice-item').forEach(item => {
|
||||||
@ -57,6 +83,28 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function appendMessage(msg) {
|
||||||
|
const messagesList = document.getElementById('messages-list');
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
|||||||
@ -12,7 +12,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
try {
|
try {
|
||||||
$stmt = db()->prepare("INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO users (username, email, password_hash) VALUES (?, ?, ?)");
|
||||||
$stmt->execute([$username, $email, $hash]);
|
$stmt->execute([$username, $email, $hash]);
|
||||||
$_SESSION['user_id'] = db()->lastInsertId();
|
$userId = db()->lastInsertId();
|
||||||
|
|
||||||
|
// Add to default server
|
||||||
|
$stmt = db()->prepare("INSERT IGNORE INTO server_members (server_id, user_id) VALUES (1, ?)");
|
||||||
|
$stmt->execute([$userId]);
|
||||||
|
|
||||||
|
$_SESSION['user_id'] = $userId;
|
||||||
header('Location: ../index.php');
|
header('Location: ../index.php');
|
||||||
exit;
|
exit;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
|||||||
@ -67,6 +67,15 @@ CREATE TABLE IF NOT EXISTS user_roles (
|
|||||||
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE
|
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS server_members (
|
||||||
|
server_id INT NOT NULL,
|
||||||
|
user_id INT NOT NULL,
|
||||||
|
joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (server_id, user_id),
|
||||||
|
FOREIGN KEY (server_id) REFERENCES servers(id) ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
-- Seed initial data
|
-- Seed initial data
|
||||||
INSERT IGNORE INTO users (id, username, email, password_hash, status) VALUES
|
INSERT IGNORE INTO users (id, username, email, password_hash, status) VALUES
|
||||||
(1, 'System', 'system@local', '$2y$10$xyz', 'online');
|
(1, 'System', 'system@local', '$2y$10$xyz', 'online');
|
||||||
@ -75,6 +84,8 @@ INSERT IGNORE INTO servers (id, name, owner_id, invite_code) VALUES
|
|||||||
(1, 'General Community', 1, 'GEN-123'),
|
(1, 'General Community', 1, 'GEN-123'),
|
||||||
(2, 'Flatlogic Devs', 1, 'DEV-456');
|
(2, 'Flatlogic Devs', 1, 'DEV-456');
|
||||||
|
|
||||||
|
INSERT IGNORE INTO server_members (server_id, user_id) VALUES (1, 1), (2, 1);
|
||||||
|
|
||||||
INSERT IGNORE INTO channels (id, server_id, name, type) VALUES
|
INSERT IGNORE INTO channels (id, server_id, name, type) VALUES
|
||||||
(1, 1, 'general', 'text'),
|
(1, 1, 'general', 'text'),
|
||||||
(2, 1, 'random', 'text'),
|
(2, 1, 'random', 'text'),
|
||||||
|
|||||||
146
index.php
146
index.php
@ -5,10 +5,20 @@ requireLogin();
|
|||||||
$user = getCurrentUser();
|
$user = getCurrentUser();
|
||||||
$current_user_id = $user['id'];
|
$current_user_id = $user['id'];
|
||||||
|
|
||||||
// Fetch servers
|
// Fetch servers user is member of
|
||||||
$servers = db()->query("SELECT * FROM servers LIMIT 10")->fetchAll();
|
$stmt = db()->prepare("
|
||||||
|
SELECT s.* FROM servers s
|
||||||
|
JOIN server_members sm ON s.id = sm.server_id
|
||||||
|
WHERE sm.user_id = ?
|
||||||
|
LIMIT 20
|
||||||
|
");
|
||||||
|
$stmt->execute([$current_user_id]);
|
||||||
|
$servers = $stmt->fetchAll();
|
||||||
$active_server_id = $_GET['server_id'] ?? ($servers[0]['id'] ?? 1);
|
$active_server_id = $_GET['server_id'] ?? ($servers[0]['id'] ?? 1);
|
||||||
|
|
||||||
|
// If no servers found, we might want to show a default or an empty state
|
||||||
|
// For now, let's assume the seed data or the first server works
|
||||||
|
|
||||||
// Fetch channels
|
// Fetch channels
|
||||||
$stmt = db()->prepare("SELECT * FROM channels WHERE server_id = ?");
|
$stmt = db()->prepare("SELECT * FROM channels WHERE server_id = ?");
|
||||||
$stmt->execute([$active_server_id]);
|
$stmt->execute([$active_server_id]);
|
||||||
@ -30,6 +40,16 @@ $messages = $stmt->fetchAll();
|
|||||||
$current_channel_name = 'general';
|
$current_channel_name = 'general';
|
||||||
foreach($channels as $c) if($c['id'] == $active_channel_id) $current_channel_name = $c['name'];
|
foreach($channels as $c) if($c['id'] == $active_channel_id) $current_channel_name = $c['name'];
|
||||||
|
|
||||||
|
// Fetch members
|
||||||
|
$stmt = db()->prepare("
|
||||||
|
SELECT u.username, u.avatar_url, u.status
|
||||||
|
FROM users u
|
||||||
|
JOIN server_members sm ON u.id = sm.user_id
|
||||||
|
WHERE sm.server_id = ?
|
||||||
|
");
|
||||||
|
$stmt->execute([$active_server_id]);
|
||||||
|
$members = $stmt->fetchAll();
|
||||||
|
|
||||||
// SEO & Env tags
|
// SEO & Env tags
|
||||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Discord-like messaging app built with PHP';
|
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Discord-like messaging app built with PHP';
|
||||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||||
@ -69,15 +89,25 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
|||||||
<?php echo mb_substr($s['name'], 0, 1); ?>
|
<?php echo mb_substr($s['name'], 0, 1); ?>
|
||||||
</a>
|
</a>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
<a href="#" class="server-icon add-btn" title="Add a Server" data-bs-toggle="modal" data-bs-target="#addServerModal">
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Channels Sidebar -->
|
<!-- Channels Sidebar -->
|
||||||
<div class="channels-sidebar">
|
<div class="channels-sidebar">
|
||||||
<div class="channels-header">
|
<div class="channels-header">
|
||||||
<?php echo htmlspecialchars($servers[0]['name'] ?? 'Server'); ?>
|
<?php
|
||||||
|
$active_server_name = 'Server';
|
||||||
|
foreach($servers as $s) if($s['id'] == $active_server_id) $active_server_name = $s['name'];
|
||||||
|
echo htmlspecialchars($active_server_name);
|
||||||
|
?>
|
||||||
</div>
|
</div>
|
||||||
<div class="channels-list">
|
<div class="channels-list">
|
||||||
<div class="channel-category">Text Channels</div>
|
<div class="channel-category">
|
||||||
|
<span>Text Channels</span>
|
||||||
|
<span class="add-channel-btn" title="Create Channel" data-bs-toggle="modal" data-bs-target="#addChannelModal" data-type="text">+</span>
|
||||||
|
</div>
|
||||||
<?php foreach($channels as $c): if($c['type'] !== 'text') continue; ?>
|
<?php foreach($channels as $c): if($c['type'] !== 'text') continue; ?>
|
||||||
<a href="?server_id=<?php echo $active_server_id; ?>&channel_id=<?php echo $c['id']; ?>"
|
<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' : ''; ?>">
|
class="channel-item <?php echo $c['id'] == $active_channel_id ? 'active' : ''; ?>">
|
||||||
@ -85,7 +115,10 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
|||||||
</a>
|
</a>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
||||||
<div class="channel-category" style="margin-top: 16px;">Voice Channels</div>
|
<div class="channel-category" style="margin-top: 16px;">
|
||||||
|
<span>Voice Channels</span>
|
||||||
|
<span class="add-channel-btn" title="Create Channel" data-bs-toggle="modal" data-bs-target="#addChannelModal" data-type="voice">+</span>
|
||||||
|
</div>
|
||||||
<?php foreach($channels as $c): if($c['type'] !== 'voice') continue; ?>
|
<?php foreach($channels as $c): if($c['type'] !== 'voice') continue; ?>
|
||||||
<div class="channel-item voice-item" data-channel-id="<?php echo $c['id']; ?>">
|
<div class="channel-item voice-item" data-channel-id="<?php echo $c['id']; ?>">
|
||||||
<?php echo htmlspecialchars($c['name']); ?>
|
<?php echo htmlspecialchars($c['name']); ?>
|
||||||
@ -150,17 +183,110 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
|||||||
|
|
||||||
<!-- Members Sidebar -->
|
<!-- Members Sidebar -->
|
||||||
<div class="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;">
|
<div style="color: var(--text-muted); font-size: 0.75em; text-transform: uppercase; font-weight: bold; margin-bottom: 16px;">
|
||||||
Online — 1
|
Members — <?php echo count($members); ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="channel-item" style="color: var(--text-primary);">
|
<?php foreach($members as $m): ?>
|
||||||
<div class="message-avatar" style="width: 32px; height: 32px; background-color: #23a559;"></div>
|
<div class="channel-item" style="color: var(--text-primary); margin-bottom: 8px;">
|
||||||
System
|
<div class="message-avatar" style="width: 32px; height: 32px; background-color: <?php echo $m['status'] == 'online' ? '#23a559' : '#80848e'; ?>; position: relative;">
|
||||||
|
<?php if($m['status'] == 'online'): ?>
|
||||||
|
<div style="position: absolute; bottom: 0; right: 0; width: 10px; height: 10px; background-color: #23a559; border-radius: 50%; border: 2px solid var(--bg-members);"></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<span style="overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||||
|
<?php echo htmlspecialchars($m['username']); ?>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Add Server Modal -->
|
||||||
|
<div class="modal fade" id="addServerModal" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Create or Join a server</h5>
|
||||||
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body p-0">
|
||||||
|
<ul class="nav nav-tabs nav-fill" id="serverTabs" role="tablist">
|
||||||
|
<li class="nav-item">
|
||||||
|
<button class="nav-link active text-white border-0 bg-transparent" id="create-tab" data-bs-toggle="tab" data-bs-target="#create-pane" type="button">Create</button>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<button class="nav-link text-white border-0 bg-transparent" id="join-tab" data-bs-toggle="tab" data-bs-target="#join-pane" type="button">Join</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content p-3">
|
||||||
|
<div class="tab-pane fade show active" id="create-pane">
|
||||||
|
<form action="api_v1_servers.php" method="POST">
|
||||||
|
<p style="color: var(--text-muted); font-size: 0.9em;">Give your new server a personality with a name.</p>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label text-uppercase fw-bold" style="font-size: 0.7em; color: var(--text-muted);">Server Name</label>
|
||||||
|
<input type="text" name="name" class="form-control" placeholder="My Awesome Server" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary w-100" style="background-color: var(--blurple); border: none;">Create Server</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane fade" id="join-pane">
|
||||||
|
<form action="api_v1_servers.php" method="POST">
|
||||||
|
<input type="hidden" name="action" value="join">
|
||||||
|
<p style="color: var(--text-muted); font-size: 0.9em;">Enter an invite code to join an existing server.</p>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label text-uppercase fw-bold" style="font-size: 0.7em; color: var(--text-muted);">Invite Code</label>
|
||||||
|
<input type="text" name="invite_code" class="form-control" placeholder="GEN-123" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-success w-100" style="background-color: #23a559; border: none;">Join Server</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Add Channel Modal -->
|
||||||
|
<div class="modal fade" id="addChannelModal" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Create Channel</h5>
|
||||||
|
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
<form action="api_v1_channels.php" method="POST">
|
||||||
|
<input type="hidden" name="server_id" value="<?php echo $active_server_id; ?>">
|
||||||
|
<input type="hidden" name="type" id="channel-type-input" value="text">
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label text-uppercase fw-bold" style="font-size: 0.7em; color: var(--text-muted);">Channel Name</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-text bg-dark border-0 text-muted" id="channel-hash-prefix">#</span>
|
||||||
|
<input type="text" name="name" class="form-control" placeholder="new-channel" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-link text-white text-decoration-none" data-bs-dismiss="modal">Cancel</button>
|
||||||
|
<button type="submit" class="btn btn-primary" style="background-color: var(--blurple); border: none; padding: 10px 24px;">Create Channel</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
<script src="assets/js/voice.js?v=<?php echo time(); ?>"></script>
|
<script src="assets/js/voice.js?v=<?php echo time(); ?>"></script>
|
||||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||||
|
<script>
|
||||||
|
// Handle channel type in modal
|
||||||
|
document.querySelectorAll('.add-channel-btn').forEach(btn => {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
const type = this.getAttribute('data-type');
|
||||||
|
document.getElementById('channel-type-input').value = type;
|
||||||
|
document.getElementById('channel-hash-prefix').textContent = type === 'text' ? '#' : '🔊';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user