// ===== State ===== let currentSort = 'new'; let currentPosts = []; let currentPostId = null; let selectedFile = null; let dragCounter = 0; // ===== Initialize ===== document.addEventListener('DOMContentLoaded', () => { loadPosts(); setupDragDrop(); setupPageDrag(); setupPasteUpload(); }); // ===== API Helpers ===== async function apiGet(endpoint) { const res = await fetch(endpoint); if (!res.ok) throw new Error(`HTTP ${res.status}`); return res.json(); } async function apiPost(endpoint, formData = null, body = null) { let res; if (formData) { res = await fetch(endpoint, { method: 'POST', body: formData }); } else { res = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); } if (!res.ok) { const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` })); throw new Error(err.error || `HTTP ${res.status}`); } return res.json(); } // ===== Posts ===== async function loadPosts() { const loading = document.getElementById('loading'); loading.style.display = 'block'; try { currentPosts = await apiGet(`/api/posts?sort=${currentSort}`); renderGallery(); } catch (err) { showToast('Failed to load posts', 'error'); } finally { loading.style.display = 'none'; } } function renderGallery() { const gallery = document.getElementById('gallery'); const count = document.getElementById('postCount'); count.textContent = `${currentPosts.length} posts`; if (currentPosts.length === 0) { gallery.innerHTML = '
No comments yet. Be the first!
'; return; } const topLevel = postComments.filter(c => !c.parentId); const replies = postComments.filter(c => c.parentId); list.innerHTML = topLevel.map(c => { const childReplies = replies.filter(r => r.parentId === c.id); return `