feat(update-modal): display last 5 release notes instead of single

- Modified backend to fetch last 5 releases from GitHub API
- Updated frontend to iterate through and display multiple releases
- Added latest badge and publish date styling
- Added update.latestBadge translation key to all locales
- Maintains backward compatibility for single changelog display
This commit is contained in:
Will Miao
2026-01-23 22:19:43 +08:00
parent 0bb75fdf77
commit 7bba24c19f
15 changed files with 180 additions and 52 deletions

View File

@@ -121,4 +121,49 @@
.changelog-item a:hover {
text-decoration: underline;
}
}
/* Multiple releases styling */
.changelog-content > .changelog-item + .changelog-item {
margin-top: var(--space-4);
padding-top: var(--space-4);
border-top: 1px solid var(--lora-border);
}
.changelog-item h4 {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--space-2);
margin-bottom: var(--space-2);
font-size: 1em;
}
.changelog-item .latest-badge {
background-color: var(--lora-accent);
color: white;
padding: 2px 8px;
border-radius: 12px;
font-size: 0.75em;
font-weight: 500;
text-transform: uppercase;
}
.changelog-item .publish-date {
font-size: 0.85em;
color: var(--text-color);
opacity: 0.6;
font-weight: normal;
}
.changelog-item.latest {
background-color: rgba(66, 153, 225, 0.05);
border-radius: var(--border-radius-sm);
padding: var(--space-3);
border: 1px solid rgba(66, 153, 225, 0.2);
}
[data-theme="dark"] .changelog-item.latest {
background-color: rgba(66, 153, 225, 0.1);
border-color: rgba(66, 153, 225, 0.3);
}

View File

@@ -1,8 +1,4 @@
/* Update Modal Styles */
.update-modal {
max-width: 600px;
}
.update-header {
display: flex;
align-items: center;

View File

@@ -509,38 +509,90 @@ export class UpdateService {
}
// Update changelog content if available
if (this.updateInfo && this.updateInfo.changelog) {
if (this.updateInfo && (this.updateInfo.changelog || this.updateInfo.releases)) {
const changelogContent = modal.querySelector('.changelog-content');
if (changelogContent) {
changelogContent.innerHTML = ''; // Clear existing content
// Create changelog item
const changelogItem = document.createElement('div');
changelogItem.className = 'changelog-item';
const versionHeader = document.createElement('h4');
versionHeader.textContent = `${translate('common.status.version', {}, 'Version')} ${this.latestVersion}`;
changelogItem.appendChild(versionHeader);
// Create changelog list
const changelogList = document.createElement('ul');
if (this.updateInfo.changelog && this.updateInfo.changelog.length > 0) {
this.updateInfo.changelog.forEach(item => {
const listItem = document.createElement('li');
// Parse markdown in changelog items
listItem.innerHTML = this.parseMarkdown(item);
changelogList.appendChild(listItem);
// Check if we have multiple releases
const releases = this.updateInfo.releases;
if (releases && Array.isArray(releases) && releases.length > 0) {
// Display multiple releases (up to 5)
releases.forEach(release => {
const changelogItem = document.createElement('div');
changelogItem.className = 'changelog-item';
if (release.is_latest) {
changelogItem.classList.add('latest');
}
const versionHeader = document.createElement('h4');
if (release.is_latest) {
const badge = document.createElement('span');
badge.className = 'latest-badge';
badge.textContent = translate('update.latestBadge', {}, 'Latest');
versionHeader.appendChild(badge);
versionHeader.appendChild(document.createTextNode(' '));
}
const versionSpan = document.createElement('span');
versionSpan.className = 'version';
versionSpan.textContent = `${translate('common.status.version', {}, 'Version')} ${release.version}`;
versionHeader.appendChild(versionSpan);
if (release.published_at) {
const dateSpan = document.createElement('span');
dateSpan.className = 'publish-date';
dateSpan.textContent = this.formatRelativeTime(new Date(release.published_at).getTime());
versionHeader.appendChild(dateSpan);
}
changelogItem.appendChild(versionHeader);
// Create changelog list
const changelogList = document.createElement('ul');
if (release.changelog && release.changelog.length > 0) {
release.changelog.forEach(item => {
const listItem = document.createElement('li');
listItem.innerHTML = this.parseMarkdown(item);
changelogList.appendChild(listItem);
});
} else {
const listItem = document.createElement('li');
listItem.textContent = translate('update.noChangelogAvailable', {}, 'No detailed changelog available.');
changelogList.appendChild(listItem);
}
changelogItem.appendChild(changelogList);
changelogContent.appendChild(changelogItem);
});
} else {
// If no changelog items available
const listItem = document.createElement('li');
listItem.textContent = translate('update.noChangelogAvailable', {}, 'No detailed changelog available. Check GitHub for more information.');
changelogList.appendChild(listItem);
// Fallback: display single changelog (old behavior)
const changelogItem = document.createElement('div');
changelogItem.className = 'changelog-item';
const versionHeader = document.createElement('h4');
versionHeader.textContent = `${translate('common.status.version', {}, 'Version')} ${this.latestVersion}`;
changelogItem.appendChild(versionHeader);
const changelogList = document.createElement('ul');
if (this.updateInfo.changelog && this.updateInfo.changelog.length > 0) {
this.updateInfo.changelog.forEach(item => {
const listItem = document.createElement('li');
listItem.innerHTML = this.parseMarkdown(item);
changelogList.appendChild(listItem);
});
} else {
const listItem = document.createElement('li');
listItem.textContent = translate('update.noChangelogAvailable', {}, 'No detailed changelog available. Check GitHub for more information.');
changelogList.appendChild(listItem);
}
changelogItem.appendChild(changelogList);
changelogContent.appendChild(changelogItem);
}
changelogItem.appendChild(changelogList);
changelogContent.appendChild(changelogItem);
}
}