feat: remove image handling and update related UI elements for streamlined moderation experience

This commit is contained in:
MythEclipse
2026-05-13 21:28:45 +07:00
parent 95cb8b837a
commit 251a176b2b

View File

@@ -397,30 +397,6 @@
.badge.edit { color: var(--yellow); border-color: rgba(255,228,94,0.36); } .badge.edit { color: var(--yellow); border-color: rgba(255,228,94,0.36); }
.badge.delete { color: var(--red); border-color: rgba(255,79,109,0.42); } .badge.delete { color: var(--red); border-color: rgba(255,79,109,0.42); }
.image-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 14px;
}
.image-card {
overflow: hidden;
border: 1px solid var(--line);
border-radius: 22px;
background: rgba(255,255,255,0.035);
}
.image-preview {
height: 180px;
display: grid;
place-items: center;
background: #05070b;
color: var(--faint);
font: 700 12px/1 "JetBrains Mono", monospace;
}
.image-preview img { width: 100%; height: 100%; object-fit: cover; }
.image-meta { padding: 14px; display: grid; gap: 8px; }
.filename { font-size: 13px; font-weight: 900; word-break: break-word; } .filename { font-size: 13px; font-weight: 900; word-break: break-word; }
.link { color: var(--cyan); text-decoration: none; font-weight: 900; } .link { color: var(--cyan); text-decoration: none; font-weight: 900; }
.link:hover { text-decoration: underline; } .link:hover { text-decoration: underline; }
@@ -456,8 +432,8 @@
<section class="hero"> <section class="hero">
<div class="brand-card"> <div class="brand-card">
<div class="eyebrow"><span class="pulse"></span> Discord moderation command center</div> <div class="eyebrow"><span class="pulse"></span> Discord moderation command center</div>
<h1>Voice. Text. Image. One Watch Floor.</h1> <h1>Voice. Text. One Watch Floor.</h1>
<p class="subtitle">Single-page watcher for live voice bridge, captured messages, and uploaded image evidence. Built for dense moderation review without jumping between pages.</p> <p class="subtitle">Single-page watcher for live voice bridge and captured Discord messages, including stickers, embeds, replies, and uploaded image evidence inline.</p>
</div> </div>
<div class="status-card"> <div class="status-card">
<div class="status-row"><span class="status-label">WebSocket</span><span class="status-value"><span id="wsDot" class="dot"></span><span id="wsStatusText">Connecting</span></span></div> <div class="status-row"><span class="status-label">WebSocket</span><span class="status-value"><span id="wsDot" class="dot"></span><span id="wsStatusText">Connecting</span></span></div>
@@ -470,7 +446,6 @@
<div class="tabs"> <div class="tabs">
<button class="tab-btn active" data-tab="voice">Voice</button> <button class="tab-btn active" data-tab="voice">Voice</button>
<button class="tab-btn" data-tab="text">Text</button> <button class="tab-btn" data-tab="text">Text</button>
<button class="tab-btn" data-tab="images">Images</button>
</div> </div>
<div class="filter-row"> <div class="filter-row">
<span>Channel / Thread</span> <span>Channel / Thread</span>
@@ -521,13 +496,6 @@
<div id="textList" class="feed"></div> <div id="textList" class="feed"></div>
</div> </div>
</section> </section>
<section id="images" class="tab-content">
<div class="content-card">
<div class="card-title"><h2>Image Watch</h2><span class="mini">picser raw commit</span></div>
<div id="imageGrid" class="image-grid"></div>
</div>
</section>
</main> </main>
<script> <script>
@@ -536,7 +504,6 @@
activeTab: 'voice', activeTab: 'voice',
selectedChannel: '', selectedChannel: '',
text: [], text: [],
images: [],
isStreaming: false, isStreaming: false,
isListening: false, isListening: false,
audioContextTransmit: null, audioContextTransmit: null,
@@ -568,7 +535,6 @@
visualizer: document.getElementById('visualizer'), visualizer: document.getElementById('visualizer'),
userList: document.getElementById('userList'), userList: document.getElementById('userList'),
textList: document.getElementById('textList'), textList: document.getElementById('textList'),
imageGrid: document.getElementById('imageGrid'),
}; };
for (let i = 0; i < 32; i++) { for (let i = 0; i < 32; i++) {
@@ -714,7 +680,7 @@
if (item) Object.assign(item, { deleted_at: message.data.deleted_at, type: 'deleted' }); if (item) Object.assign(item, { deleted_at: message.data.deleted_at, type: 'deleted' });
renderText(); renderText();
} }
if (message.type === 'attachment_uploaded') fetchImages(); if (message.type === 'attachment_uploaded') fetchText();
} }
function renderUsers(users) { function renderUsers(users) {
@@ -746,13 +712,6 @@
renderText(); renderText();
} }
async function fetchImages() {
if (!state.selectedChannel) return renderImages();
const result = await apiRequest(`/api/messages?channel=${encodeURIComponent(state.selectedChannel)}&type=image&limit=80`);
state.images = result.data || [];
renderImages();
}
function parseMetadata(value) { function parseMetadata(value) {
if (!value) return {}; if (!value) return {};
try { return JSON.parse(value); } catch { return {}; } try { return JSON.parse(value); } catch { return {}; }
@@ -876,46 +835,6 @@
return wrap; return wrap;
} }
function renderImages() {
el.imageGrid.replaceChildren();
if (!state.selectedChannel) return appendEmpty(el.imageGrid, 'Select channel to view image captures');
if (state.images.length === 0) return appendEmpty(el.imageGrid, 'No image captures yet');
for (const image of state.images) {
const card = document.createElement('article');
card.className = 'image-card';
const preview = document.createElement('div');
preview.className = 'image-preview';
if (image.uploaded_url) {
const img = document.createElement('img');
img.src = image.uploaded_url;
img.alt = image.filename;
preview.appendChild(img);
} else {
preview.textContent = image.upload_status || 'pending';
}
const meta = document.createElement('div');
meta.className = 'image-meta';
const filename = document.createElement('div');
filename.className = 'filename';
filename.textContent = image.filename;
const info = document.createElement('div');
info.className = 'time';
info.textContent = `${(image.size / 1024).toFixed(1)}KB • ${image.upload_status}${image.thread_id ? ' • thread' : ''}`;
meta.append(filename, info);
if (image.uploaded_url) {
const link = document.createElement('a');
link.className = 'link';
link.href = image.uploaded_url;
link.target = '_blank';
link.rel = 'noreferrer';
link.textContent = 'open raw commit';
meta.appendChild(link);
}
card.append(preview, meta);
el.imageGrid.appendChild(card);
}
}
function appendBadge(parent, label, className) { function appendBadge(parent, label, className) {
const badge = document.createElement('span'); const badge = document.createElement('span');
badge.className = `badge ${className}`; badge.className = `badge ${className}`;
@@ -1015,7 +934,6 @@
document.getElementById(state.activeTab).classList.add('active'); document.getElementById(state.activeTab).classList.add('active');
el.activeTabLabel.textContent = button.textContent; el.activeTabLabel.textContent = button.textContent;
if (state.activeTab === 'text') await fetchText(); if (state.activeTab === 'text') await fetchText();
if (state.activeTab === 'images') await fetchImages();
}); });
}); });
@@ -1026,14 +944,13 @@
el.listenBtn.addEventListener('click', toggleListen); el.listenBtn.addEventListener('click', toggleListen);
el.channelFilter.addEventListener('change', async () => { el.channelFilter.addEventListener('change', async () => {
state.selectedChannel = el.channelFilter.value; state.selectedChannel = el.channelFilter.value;
await Promise.all([fetchText(), fetchImages()]).catch((error) => showError(error.message)); await fetchText().catch((error) => showError(error.message));
}); });
connectWebSocket(); connectWebSocket();
loadGuilds().then(refreshStatus).catch((error) => showError(error.message)); loadGuilds().then(refreshStatus).catch((error) => showError(error.message));
setInterval(() => { setInterval(() => {
if (state.activeTab === 'text') fetchText().catch(() => {}); if (state.activeTab === 'text') fetchText().catch(() => {});
if (state.activeTab === 'images') fetchImages().catch(() => {});
}, 7000); }, 7000);
</script> </script>
</body> </body>