feat: add release notes overlay with Markdown rendering

- Replace truncated plaintext release notes with full-screen overlay
  rendered via `marked` library
- Server reconnection does a hard page reload instead of custom event
This commit is contained in:
2026-03-25 21:34:59 +03:00
parent f4da47ca2b
commit 2eeae4a7c1
11 changed files with 167 additions and 25 deletions
@@ -448,6 +448,79 @@
min-height: 0;
}
/* ── Release notes content ─────────────────────────────────── */
.release-notes-content {
flex: 1;
overflow-y: auto;
padding: 1rem 1.5rem;
font-size: 0.9rem;
line-height: 1.6;
color: var(--text-color);
background: var(--bg-secondary);
border-radius: 8px;
}
.release-notes-content h2,
.release-notes-content h3,
.release-notes-content h4 {
margin: 1.2em 0 0.4em;
color: var(--text-color);
}
.release-notes-content h2 { font-size: 1.2rem; }
.release-notes-content h3 { font-size: 1.05rem; }
.release-notes-content h4 { font-size: 0.95rem; }
.release-notes-content pre {
background: #0d0d0d;
color: #d4d4d4;
padding: 0.75rem 1rem;
border-radius: 6px;
overflow-x: auto;
font-size: 0.82rem;
}
.release-notes-content code {
background: var(--bg-tertiary, #2a2a2a);
padding: 0.15em 0.4em;
border-radius: 3px;
font-size: 0.88em;
}
.release-notes-content pre code {
background: none;
padding: 0;
}
.release-notes-content a {
color: var(--primary-color);
}
.release-notes-content hr {
border: none;
border-top: 1px solid var(--border-color);
margin: 1rem 0;
}
.release-notes-content table {
width: 100%;
border-collapse: collapse;
margin: 0.5rem 0;
}
.release-notes-content th,
.release-notes-content td {
border: 1px solid var(--border-color);
padding: 0.4rem 0.6rem;
text-align: left;
font-size: 0.85rem;
}
.release-notes-content th {
background: var(--bg-tertiary, #2a2a2a);
}
/* ── Log viewer base ───────────────────────────────────────── */
.log-viewer-output {
@@ -203,6 +203,7 @@ import {
loadUpdateStatus, initUpdateListener, checkForUpdates,
loadUpdateSettings, saveUpdateSettings, dismissUpdate,
initUpdateSettingsPanel, applyUpdate,
openReleaseNotes, closeReleaseNotes,
} from './features/update.ts';
// ─── Register all HTML onclick / onchange / onfocus globals ───
@@ -572,6 +573,8 @@ Object.assign(window, {
dismissUpdate,
initUpdateSettingsPanel,
applyUpdate,
openReleaseNotes,
closeReleaseNotes,
// appearance
applyStylePreset,
@@ -228,8 +228,9 @@ export async function loadServerInfo() {
const wasOffline = _serverOnline === false;
_setConnectionState(true);
if (wasOffline) {
// Server came back — reload data
window.dispatchEvent(new CustomEvent('server:reconnected'));
// Server came back — hard reload to ensure fresh data
location.reload();
return;
}
// Auth mode detection
@@ -36,6 +36,7 @@ interface UpdateStatus {
}
let _lastStatus: UpdateStatus | null = null;
let _releaseNotesBody = '';
// ─── Version badge highlight ────────────────────────────────
@@ -383,18 +384,33 @@ function _renderUpdatePanel(status: UpdateStatus): void {
progressBar.parentElement!.style.display = show ? '' : 'none';
}
// Release notes preview
const notesEl = document.getElementById('update-release-notes');
if (notesEl) {
// Release notes button visibility
const notesGroup = document.getElementById('update-release-notes-group');
if (notesGroup) {
if (status.has_update && status.release && status.release.body) {
const truncated = status.release.body.length > 500
? status.release.body.slice(0, 500) + '...'
: status.release.body;
notesEl.textContent = truncated;
notesEl.parentElement!.style.display = '';
_releaseNotesBody = status.release.body;
notesGroup.style.display = '';
} else {
notesEl.textContent = '';
notesEl.parentElement!.style.display = 'none';
_releaseNotesBody = '';
notesGroup.style.display = 'none';
}
}
}
// ─── Release Notes Overlay ─────────────────────────────────
export function openReleaseNotes(): void {
const overlay = document.getElementById('release-notes-overlay');
const content = document.getElementById('release-notes-content');
if (overlay && content) {
import('marked').then(({ marked }) => {
content.innerHTML = marked.parse(_releaseNotesBody) as string;
overlay.style.display = 'flex';
});
}
}
export function closeReleaseNotes(): void {
const overlay = document.getElementById('release-notes-overlay');
if (overlay) overlay.style.display = 'none';
}
@@ -1931,6 +1931,7 @@
"update.last_check": "Last check",
"update.never": "never",
"update.release_notes": "Release Notes",
"update.view_release_notes": "View Release Notes",
"update.auto_check_label": "Auto-Check Settings",
"update.auto_check_hint": "Periodically check for new releases in the background.",
"update.enable": "Enable auto-check",
@@ -1860,6 +1860,7 @@
"update.last_check": "Последняя проверка",
"update.never": "никогда",
"update.release_notes": "Примечания к релизу",
"update.view_release_notes": "Открыть примечания к релизу",
"update.auto_check_label": "Автоматическая проверка",
"update.auto_check_hint": "Периодически проверять наличие новых версий в фоновом режиме.",
"update.enable": "Включить автопроверку",
@@ -1858,6 +1858,7 @@
"update.last_check": "上次检查",
"update.never": "从未",
"update.release_notes": "发布说明",
"update.view_release_notes": "查看发布说明",
"update.auto_check_label": "自动检查设置",
"update.auto_check_hint": "在后台定期检查新版本。",
"update.enable": "启用自动检查",