diff --git a/src/app/pages/Changelog.tsx b/src/app/pages/Changelog.tsx index 5e80d2de..69a26b55 100644 --- a/src/app/pages/Changelog.tsx +++ b/src/app/pages/Changelog.tsx @@ -3,7 +3,7 @@ import { useEffect, useMemo, useState } from 'preact/hooks' import { Ad, ErrorPanel, Octicon, TextInput } from '../components' import { locale } from '../Locales' import type { VersionId } from '../Schemas' -import type { ChangelogEntry } from '../services/Changelogs' +import type { ChangelogEntry, ChangelogVersion } from '../services/Changelogs' import { getChangelogs } from '../services/Changelogs' import { hashString } from '../Utils' @@ -26,9 +26,11 @@ export function Changelog({ lang, changeTitle }: ChangelogProps) { const [search, setSearch] = useState('') const [tags, setTags] = useState([]) - const addTag = (tag: string) => { + const toggleTag = (tag: string) => { if (!tags.includes(tag)) { setTags([...tags, tag]) + } else { + setTags(tags.filter(t => t !== tag)) } } @@ -56,7 +58,7 @@ export function Changelog({ lang, changeTitle }: ChangelogProps) {
{filteredChangelogs.map(change => - )} + )}
} @@ -64,18 +66,27 @@ export function Changelog({ lang, changeTitle }: ChangelogProps) { type ChangeProps = { change: ChangelogEntry, activeTags: string[], - addTag: (tag: string) => unknown, + toggleTag: (tag: string) => unknown, } -function Change({ change, activeTags, addTag }: ChangeProps) { +function Change({ change, activeTags, toggleTag }: ChangeProps) { return
+
+ + +
- {change.tags.map(tag => addTag(tag)} active={activeTags.includes(tag)} />)} - {change.version} + {change.tags.map(tag => toggleTag(tag)} active={activeTags.includes(tag)} />)}
} +function ArticleLink({ id, article }: ChangelogVersion) { + return article === null + ? {id} + : {id} +} + type TagProps = { label: string, active?: boolean, diff --git a/src/app/services/Changelogs.ts b/src/app/services/Changelogs.ts index e3a2f79b..8958f5cc 100644 --- a/src/app/services/Changelogs.ts +++ b/src/app/services/Changelogs.ts @@ -1,33 +1,40 @@ +import { isObject } from '../Utils' + const repo = 'https://raw.githubusercontent.com/misode/technical-changes/main' export type ChangelogEntry = { - group: string, - version: string, + group: ChangelogVersion, + version: ChangelogVersion, tags: string[], content: string, } +export type ChangelogVersion = { + id: string, + article: string | null, +} + let Changelogs: ChangelogEntry[] | Promise | null = null export async function getChangelogs() { if (!Changelogs) { const index = await (await fetch(`${repo}/index.json`)).json() as string[] Changelogs = (await Promise.all( - index.map(group => fetchGroup(group)) + index.map(group => fetchGroup(parseVersion(group))) )).flat() } return Changelogs } -async function fetchGroup(group: string) { - const index = await (await fetch(`${repo}/${group}/index.json`)).json() as string[] +async function fetchGroup(group: ChangelogVersion) { + const index = await (await fetch(`${repo}/${group.id}/index.json`)).json() as string[] return (await Promise.all( - index.map(version => fetchChangelog(group, version)) + index.map(version => fetchChangelog(group, parseVersion(version))) )).flat() } -async function fetchChangelog(group: string, version: string) { - const text = await (await fetch(`${repo}/${group}/${version}.md`)).text() +async function fetchChangelog(group: ChangelogVersion, version: ChangelogVersion) { + const text = await (await fetch(`${repo}/${group.id}/${version.id}.md`)).text() return parseChangelog(text).map(change => ({ version, group, @@ -47,3 +54,15 @@ function parseChangelog(text: string) { } }) } + +function parseVersion(version: unknown): ChangelogVersion { + if (typeof version === 'string') { + return { + id: version, + article: version.match(/\d\dw\d\d[a-z]/) ? 'minecraft-snapshot-' + version : version.match(/\d+\.\d+(\.\d+)?-pre[0-9]+/) ? 'minecraft-' + version.replaceAll('.', '-').replaceAll('pre', 'pre-release-') : null, + } + } else if (isObject(version)) { + return version as ChangelogVersion + } + return { id: 'unknown', article: null } +} diff --git a/src/styles/global.css b/src/styles/global.css index d064b6fe..a0068905 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -1004,7 +1004,7 @@ hr { .changelog-tags { display: flex; - margin-bottom: 8px; + flex-wrap: wrap; } .changelog-tag { @@ -1018,12 +1018,17 @@ hr { padding: 0 8px; color: var(--color); fill: var(--color); + white-space: nowrap; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; } +.changelog-entry .changelog-tag { + margin-bottom: 8px; +} + .changelog-tag svg { margin-right: 4px; width: 20px; @@ -1041,13 +1046,31 @@ hr { } .changelog-version { + float: right; +} + +.changelog-version > * { margin-left: auto; font-size: 15px; color: var(--text-3); text-decoration: none; } -.changelog-version:hover { +.changelog-version > *:first-child { + position: relative; + margin-right: 19px; +} + +.changelog-version > *:first-child::after { + content: '•'; + position: absolute; + text-decoration: none; + right: -12px; + top: 0; + pointer-events: none; +} + +.changelog-version a:hover { text-decoration: underline; }