Skip to content

Commit fdbf2e5

Browse files
feat: improve changelogs page (#1274)
* feat: improve changelogs page - by default only show releases notes of installed version - menu to select and read `latest`, `beta`, etc - linkify the mentions and pr number similar to github * fix: formatting * Update src/pages/changelog/changelog.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: formatting --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 807b45e commit fdbf2e5

File tree

2 files changed

+198
-14
lines changed

2 files changed

+198
-14
lines changed

src/pages/changelog/changelog.js

Lines changed: 164 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,186 @@
1+
import fsOperation from "fileSystem";
12
import "./style.scss";
3+
import Contextmenu from "components/contextmenu";
24
import Page from "components/page";
5+
import Ref from "html-tag-js/ref";
36
import actionStack from "lib/actionStack";
47
import markdownIt from "markdown-it";
58
import markdownItTaskLists from "markdown-it-task-lists";
69
import helpers from "utils/helpers";
710

811
export default async function Changelog() {
9-
const CHANGELOG_URL =
10-
"https://raw.githubusercontent.com/deadlyjack/Acode/main/CHANGELOG.md";
11-
const $page = Page(strings["changelog"]);
12-
const $content = <div className="md" id="changelog"></div>;
12+
const GITHUB_API_URL =
13+
"https://api.github.com/repos/Acode-Foundation/Acode/releases";
14+
const CHANGELOG_FILE_URL =
15+
"https://raw.githubusercontent.com/Acode-Foundation/Acode/main/CHANGELOG.md";
16+
const currentVersion = BuildInfo.version;
1317

14-
$content.innerHTML = '<div class="loading">Loading changelog...</div>';
18+
let selectedVersion = currentVersion;
19+
let selectedStatus = "current";
20+
const versionIndicatorRef = new Ref();
21+
const versionTextRef = new Ref();
22+
23+
const versionSelector = (
24+
<div className="changelog-version-selector" data-action="select-version">
25+
<span
26+
className={"status-indicator status-" + selectedStatus}
27+
ref={versionIndicatorRef}
28+
></span>
29+
<span ref={versionTextRef}>{selectedVersion}</span>
30+
</div>
31+
);
1532

33+
const $page = Page(strings["changelog"], {
34+
tail: versionSelector,
35+
});
36+
37+
const versionSelectorMenu = Contextmenu({
38+
top: "36px",
39+
right: "5px",
40+
toggler: versionSelector,
41+
transformOrigin: "top right",
42+
innerHTML: () => {
43+
return `
44+
<li action="current">
45+
<span class="text">Current Version (${currentVersion})</span>
46+
</li>
47+
<li action="latest">
48+
<span class="text">Latest Release</span>
49+
</li>
50+
<li action="beta">
51+
<span class="text">Beta Version</span>
52+
</li>
53+
<li action="full">
54+
<span class="text">Full Changelog</span>
55+
</li>
56+
`;
57+
},
58+
});
59+
60+
const $content = <div className="md" id="changelog"></div>;
61+
$content.innerHTML = '<div class="loading">Loading changelog...</div>';
1662
$page.content = $content;
1763
app.append($page);
1864

19-
try {
20-
const changeLog = await fetch(CHANGELOG_URL);
21-
const changeLogText = await changeLog.text();
65+
async function loadLatestRelease() {
66+
try {
67+
const releases = await fsOperation(`${GITHUB_API_URL}/latest`).readFile(
68+
"json",
69+
);
70+
selectedVersion = releases.tag_name.replace("v", "");
71+
selectedStatus = "latest";
72+
updateVersionSelector();
73+
return renderChangelog(releases.body);
74+
} catch (error) {
75+
$content.innerHTML =
76+
'<div class="error">Failed to load latest release notes</div>';
77+
}
78+
}
2279

23-
const cleanedText = changeLogText.replace(/^#\s*Change\s*Log\s*\n*/i, "");
80+
async function loadBetaRelease() {
81+
try {
82+
const releases = await fsOperation(GITHUB_API_URL).readFile("json");
83+
const betaRelease = releases.find((r) => r.prerelease);
84+
if (!betaRelease) {
85+
$content.innerHTML = '<div class="error">No beta release found</div>';
86+
return;
87+
}
88+
selectedVersion = betaRelease.tag_name.replace("v", "");
89+
selectedStatus = "prerelease";
90+
updateVersionSelector();
91+
return renderChangelog(betaRelease.body);
92+
} catch (error) {
93+
$content.innerHTML =
94+
'<div class="error">Failed to load beta release notes</div>';
95+
}
96+
}
2497

25-
const htmlContent = markdownIt({ html: true })
26-
.use(markdownItTaskLists)
27-
.render(cleanedText);
98+
async function loadFullChangelog() {
99+
try {
100+
const changeLogText =
101+
await fsOperation(CHANGELOG_FILE_URL).readFile("utf8");
102+
const cleanedText = changeLogText.replace(/^#\s*Change\s*Log\s*\n*/i, "");
103+
selectedVersion = "Changelogs.md";
104+
selectedStatus = "current";
105+
updateVersionSelector();
106+
return renderChangelog(cleanedText);
107+
} catch (error) {
108+
$content.innerHTML =
109+
'<div class="error">Failed to load full changelog</div>';
110+
}
111+
}
112+
113+
async function loadVersionChangelog() {
114+
try {
115+
const releases = await fsOperation(GITHUB_API_URL).readFile("json");
116+
const currentRelease = releases.find(
117+
(r) => r.tag_name.replace("v", "") === currentVersion,
118+
);
119+
selectedVersion = currentVersion;
120+
selectedStatus = "current";
121+
updateVersionSelector();
122+
if (currentRelease) {
123+
return renderChangelog(currentRelease.body);
124+
} else {
125+
return loadLatestRelease();
126+
}
127+
} catch (error) {
128+
$content.innerHTML =
129+
'<div class="error">Failed to load version changelog</div>';
130+
}
131+
}
28132

133+
function renderChangelog(text) {
134+
const md = markdownIt({ html: true, linkify: true });
135+
const REPO_URL = "https://github.com/Acode-Foundation/Acode";
136+
let processedText = text
137+
// Convert full PR URLs to #number format with links preserved in markdown
138+
.replace(
139+
/https:\/\/github\.com\/Acode-Foundation\/Acode\/pull\/(\d+)/g,
140+
"[#$1](https://github.com/Acode-Foundation/Acode/pull/$1)",
141+
)
142+
// Convert existing #number references to links if they aren't already
143+
.replace(
144+
/(?<!\[)#(\d+)(?!\])/g,
145+
"[#$1](https://github.com/Acode-Foundation/Acode/pull/$1)",
146+
)
147+
// Convert @username mentions to GitHub profile links
148+
.replace(/@(\w+)/g, "[@$1](https://github.com/$1)");
149+
150+
md.use(markdownItTaskLists);
151+
const htmlContent = md.render(processedText);
29152
$content.innerHTML = htmlContent;
30-
} catch (error) {
31-
$content.innerHTML = '<div class="error">Failed to load changelog</div>';
32153
}
33154

155+
function updateVersionSelector() {
156+
versionTextRef.textContent = selectedVersion;
157+
versionIndicatorRef.className = "status-indicator status-" + selectedStatus;
158+
}
159+
160+
versionSelectorMenu.onclick = async function (e) {
161+
const action = e.target.closest("li")?.getAttribute("action");
162+
if (!action) return;
163+
versionSelectorMenu.hide();
164+
165+
switch (action) {
166+
case "current":
167+
await loadVersionChangelog();
168+
break;
169+
case "latest":
170+
await loadLatestRelease();
171+
break;
172+
case "beta":
173+
await loadBetaRelease();
174+
break;
175+
case "full":
176+
await loadFullChangelog();
177+
break;
178+
}
179+
};
180+
181+
// Load current version changelog by default
182+
loadVersionChangelog();
183+
34184
$page.onhide = function () {
35185
actionStack.remove("changelog");
36186
};

src/pages/changelog/style.scss

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,40 @@
55
padding: 0 1rem;
66
}
77

8+
.changelog-version-selector {
9+
display: flex;
10+
align-items: center;
11+
gap: 8px;
12+
background-color: var(--popup-background-color);
13+
border: none;
14+
border-radius: 8px;
15+
padding: 8px 16px;
16+
font-weight: 500;
17+
cursor: pointer;
18+
transition: all 0.2s ease;
19+
margin-right: 6px;
20+
21+
&:hover {
22+
background-color: var(--secondary-color);
23+
}
24+
}
25+
26+
.status-indicator {
27+
display: inline-block;
28+
width: 8px;
29+
height: 8px;
30+
border-radius: 50%;
31+
}
32+
.status-latest {
33+
background-color: #10b981;
34+
}
35+
.status-prerelease {
36+
background-color: var(--danger-color);
37+
}
38+
.status-current {
39+
background-color: var(--active-icon-color);
40+
}
41+
842
.loading {
943
display: flex;
1044
justify-content: center;

0 commit comments

Comments
 (0)