diff --git a/app.js b/app.js index 5a028f6..06ec5d6 100644 --- a/app.js +++ b/app.js @@ -187,6 +187,65 @@ function animate() { animate(); +// === CHANGELOG PANEL === +(function initChangelog() { + const panel = document.getElementById('changelog-panel'); + const toggleBtn = document.getElementById('changelog-toggle'); + const closeBtn = document.getElementById('changelog-close'); + const list = document.getElementById('changelog-list'); + + /** + * Renders changelog entries into the list element. + * @param {Array<{hash: string, date: string, author: string, message: string}>} entries + * @returns {void} + */ + function renderEntries(entries) { + list.innerHTML = ''; + for (const entry of entries) { + const li = document.createElement('li'); + li.className = 'changelog-entry'; + + const authorClass = 'changelog-author author-' + entry.author; + li.innerHTML = + '
' + + ''; + + list.appendChild(li); + } + } + + fetch('changelog.json') + .then((/** @type {Response} */ res) => res.json()) + .then((/** @type {Array<{hash: string, date: string, author: string, message: string}>} */ entries) => { + renderEntries(entries); + }) + .catch(() => { + const li = document.createElement('li'); + li.className = 'changelog-entry'; + li.innerHTML = ''; + list.appendChild(li); + }); + + toggleBtn.addEventListener('click', () => { + const isVisible = panel.classList.toggle('visible'); + toggleBtn.style.backgroundColor = isVisible + ? 'var(--color-primary)' + : 'var(--color-secondary)'; + toggleBtn.style.color = isVisible + ? 'var(--color-bg)' + : 'var(--color-text)'; + }); + + closeBtn.addEventListener('click', () => { + panel.classList.remove('visible'); + toggleBtn.style.backgroundColor = 'var(--color-secondary)'; + toggleBtn.style.color = 'var(--color-text)'; + }); +}()); + // === DEBUG MODE === let debugMode = false; diff --git a/changelog.json b/changelog.json new file mode 100644 index 0000000..385b2e7 --- /dev/null +++ b/changelog.json @@ -0,0 +1,17 @@ +[ + {"hash":"440e31e","date":"2026-03-24","author":"claude","message":"Add photo mode with camera controls and depth of field"}, + {"hash":"2ebd153","date":"2026-03-24","author":"claude","message":"Add test harness for scene validation"}, + {"hash":"4f853aa","date":"2026-03-24","author":"claude","message":"World map overview mode — press Tab for bird's-eye view"}, + {"hash":"316ce63","date":"2026-03-24","author":"claude","message":"Add JSDoc types to all function parameters"}, + {"hash":"7eca0fb","date":"2026-03-24","author":"groq","message":"Debug mode — visualize collision boxes and light sources"}, + {"hash":"3934a7b","date":"2026-03-24","author":"claude","message":"Constellation system — connect nearby stars with faint lines"}, + {"hash":"554a4a0","date":"2026-03-24","author":"groq","message":"WebSocket stub for future live multiplayer"}, + {"hash":"8767f2c","date":"2026-03-24","author":"groq","message":"Manifest.json for PWA install"}, + {"hash":"4c4b776","date":"2026-03-24","author":"groq","message":"Meta tags for SEO and social sharing"}, + {"hash":"b40b7d9","date":"2026-03-24","author":"groq","message":"Ambient sound toggle for the Nexus"}, + {"hash":"db354e8","date":"2026-03-24","author":"claude","message":"NIP-07 visitor identity in the workshop"}, + {"hash":"a377da0","date":"2026-03-24","author":"claude","message":"Agent idle behaviors in 3D world"}, + {"hash":"d0edfe8","date":"2026-03-24","author":"claude","message":"Portal system — entry points to other worlds"}, + {"hash":"e293fbf","date":"2026-03-24","author":"manus","message":"Sovereign Memory Vault — 3D Knowledge Store"}, + {"hash":"6587869","date":"2026-03-24","author":"manus","message":"Three.js scene foundation"} +] diff --git a/index.html b/index.html index 26344f3..eb68ed9 100644 --- a/index.html +++ b/index.html @@ -33,9 +33,21 @@ + + +