feat: add changelog panel showing recent Nexus updates from git log
Some checks failed
CI / validate (pull_request) Failing after 19s

Adds a toggleable LOG panel (bottom-left) that fetches changelog.json
and displays recent commits with date, author badge, and message.
Includes CSS styling consistent with the dark space theme.

Fixes #130
This commit is contained in:
Alexander Whitestone
2026-03-24 00:08:04 -04:00
parent 2ebd153493
commit 534ae6f004
4 changed files with 205 additions and 0 deletions

59
app.js
View File

@@ -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 =
'<div class="changelog-meta">' +
'<span class="changelog-date">' + entry.date + '</span>' +
'<span class="' + authorClass + '">' + entry.author + '</span>' +
'</div>' +
'<div class="changelog-message">' + entry.message + '</div>';
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 = '<div class="changelog-message" style="color:var(--color-text-muted)">No changelog available.</div>';
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;

17
changelog.json Normal file
View File

@@ -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"}
]

View File

@@ -33,9 +33,21 @@
<button id="debug-toggle" class="chat-toggle-btn" aria-label="Toggle debug mode" style="background-color: var(--color-secondary); color: var(--color-bg); padding: 4px 8px; border-radius: 4px; font-size: 12px; cursor: pointer;">
🔍
</button>
<button id="changelog-toggle" class="chat-toggle-btn" aria-label="Toggle changelog" style="background-color: var(--color-secondary); color: var(--color-text); padding: 4px 8px; border-radius: 4px; font-size: 12px; cursor: pointer;">
LOG
</button>
<audio id="ambient-sound" src="ambient.mp3" loop></audio>
</div>
<!-- Changelog Panel -->
<div id="changelog-panel" aria-label="Recent Nexus updates">
<div id="changelog-header">
<span id="changelog-title">NEXUS CHANGELOG</span>
<button id="changelog-close" aria-label="Close changelog"></button>
</div>
<ul id="changelog-list"></ul>
</div>
<div id="overview-indicator">
<span>MAP VIEW</span>
<span class="overview-hint">[Tab] to exit</span>

117
style.css
View File

@@ -106,3 +106,120 @@ canvas {
0%, 100% { opacity: 0.7; }
50% { opacity: 1; }
}
/* === CHANGELOG PANEL === */
#changelog-panel {
display: none;
position: fixed;
bottom: 16px;
left: 16px;
width: 320px;
max-height: 400px;
background: rgba(0, 0, 8, 0.88);
border: 1px solid var(--color-secondary);
border-radius: 6px;
z-index: 20;
font-family: var(--font-body);
font-size: 11px;
overflow: hidden;
box-shadow: 0 0 20px rgba(68, 136, 255, 0.15);
}
#changelog-panel.visible {
display: flex;
flex-direction: column;
}
#changelog-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
border-bottom: 1px solid var(--color-secondary);
background: rgba(51, 68, 136, 0.3);
}
#changelog-title {
color: var(--color-primary);
letter-spacing: 0.15em;
text-transform: uppercase;
font-size: 10px;
}
#changelog-close {
background: none;
border: none;
color: var(--color-text-muted);
cursor: pointer;
font-family: var(--font-body);
font-size: 12px;
padding: 0 2px;
line-height: 1;
}
#changelog-close:hover {
color: var(--color-text);
}
#changelog-list {
list-style: none;
overflow-y: auto;
max-height: 340px;
padding: 8px 0;
}
#changelog-list::-webkit-scrollbar {
width: 4px;
}
#changelog-list::-webkit-scrollbar-track {
background: transparent;
}
#changelog-list::-webkit-scrollbar-thumb {
background: var(--color-secondary);
border-radius: 2px;
}
.changelog-entry {
padding: 6px 12px;
border-bottom: 1px solid rgba(51, 68, 136, 0.2);
}
.changelog-entry:last-child {
border-bottom: none;
}
.changelog-meta {
display: flex;
gap: 8px;
margin-bottom: 2px;
}
.changelog-date {
color: var(--color-text-muted);
font-size: 10px;
}
.changelog-author {
font-size: 10px;
padding: 0 4px;
border-radius: 2px;
background: rgba(68, 136, 255, 0.15);
color: var(--color-primary);
}
.changelog-author.author-groq {
background: rgba(255, 136, 68, 0.15);
color: #ff8844;
}
.changelog-author.author-manus {
background: rgba(136, 255, 68, 0.15);
color: #88ff44;
}
.changelog-message {
color: var(--color-text);
line-height: 1.4;
}