@@ -7,26 +7,97 @@ import Container from "../common/uiLibrary/container";
77import PageHeading from "../common/uiLibrary/PageHeading" ;
88import BuildComponent from "./buildComponent" ;
99import LoadingBuild from "./loading" ;
10+ import BuildStatsComponent from "./buildStatsComponent" ;
11+ import LatestReleaseComponent from "./latestReleaseComponent" ;
12+
13+ interface ReleaseInfo {
14+ version : string ;
15+ commitSha : string ;
16+ }
17+
18+ interface GitHubTag {
19+ name : string ;
20+ commit : {
21+ url : string ;
22+ sha : string ;
23+ } ;
24+ }
1025
1126const fetchChangelog = async ( url : string ) : Promise < AllChangesResponse > => {
1227 const response = await fetch ( url ) ;
1328 return await response . json ( ) ;
1429}
1530
31+ const fetchLatestRelease = async ( ) : Promise < ReleaseInfo | null > => {
32+ try {
33+ const response = await fetch ( 'https://api.github.com/repos/unitystation/unitystation/tags' ) ;
34+ const data = await response . json ( ) ;
35+
36+ if ( data && data . length > 0 ) {
37+ const goodFileTags = data
38+ . filter ( ( tag : GitHubTag ) => tag . name . startsWith ( 'good-file-' ) )
39+ . sort ( ( a : GitHubTag , b : GitHubTag ) => {
40+ const versionA = a . name . replace ( 'good-file-' , '' ) . split ( '.' ) . map ( Number ) ;
41+ const versionB = b . name . replace ( 'good-file-' , '' ) . split ( '.' ) . map ( Number ) ;
42+ for ( let i = 0 ; i < Math . max ( versionA . length , versionB . length ) ; i ++ ) {
43+ const numA = versionA [ i ] || 0 ;
44+ const numB = versionB [ i ] || 0 ;
45+ if ( numA !== numB ) {
46+ return numB - numA ; // Higher version first
47+ }
48+ }
49+ return 0 ;
50+ } ) ;
51+
52+ if ( goodFileTags . length > 0 ) {
53+ const latestTag = goodFileTags [ 0 ] ;
54+ const commitResponse = await fetch ( latestTag . commit . url ) ;
55+ const commitData = await commitResponse . json ( ) ;
56+
57+ return {
58+ version : latestTag . name ,
59+ commitSha : latestTag . commit . sha ,
60+ } ;
61+ }
62+ }
63+ return null ;
64+ } catch ( error ) {
65+ console . error ( 'Error fetching latest release:' , error ) ;
66+ return null ;
67+ }
68+ } ;
69+
1670const ChangelogPage = ( ) => {
1771 const [ buildsResponse , setBuildsResponse ] = useState < AllChangesResponse > ( ) ;
1872 const [ builds , setBuilds ] = useState < Build [ ] > ( [ ] ) ;
1973 const [ isLoading , setIsLoading ] = useState < boolean > ( true ) ;
20- const INITIAL_PAGE = "https://changelog.unitystation.org/all-changes?limit=5" ;
74+ const [ releaseInfo , setReleaseInfo ] = useState < ReleaseInfo | null > ( null ) ;
75+ const [ isLoadingRelease , setIsLoadingRelease ] = useState < boolean > ( true ) ;
76+ const INITIAL_PAGE = "https://changelog.unitystation.org/all-changes?limit=10" ;
2177
2278 useEffect ( ( ) => {
23- fetchChangelog ( INITIAL_PAGE ) . then ( ( response ) => {
79+ const fetchData = async ( ) => {
2480 setIsLoading ( true ) ;
25- setBuildsResponse ( response ) ;
26- setBuilds ( response . results ) ;
27- } ) . finally (
28- ( ) => setIsLoading ( false )
29- )
81+ setIsLoadingRelease ( true ) ;
82+
83+ try {
84+ const [ changelogResponse , releaseData ] = await Promise . all ( [
85+ fetchChangelog ( INITIAL_PAGE ) ,
86+ fetchLatestRelease ( )
87+ ] ) ;
88+
89+ setBuildsResponse ( changelogResponse ) ;
90+ setBuilds ( changelogResponse . results ) ;
91+ setReleaseInfo ( releaseData ) ;
92+ } catch ( error ) {
93+ console . error ( 'Error fetching data:' , error ) ;
94+ } finally {
95+ setIsLoading ( false ) ;
96+ setIsLoadingRelease ( false ) ;
97+ }
98+ } ;
99+
100+ fetchData ( ) ;
30101 } , [ ] ) ;
31102
32103 const handleScroll = useCallback ( async ( ) => {
@@ -46,8 +117,20 @@ const ChangelogPage = () => {
46117
47118 return (
48119 < Container >
49- < PageHeading isCentered > Changelog</ PageHeading >
50120 < div className = "flex flex-col gap-4" >
121+ { ! ! builds && builds . length > 0 && (
122+ < div className = "grid grid-cols-1 md:grid-cols-2 gap-4" >
123+ < BuildStatsComponent builds = { builds } />
124+ { isLoadingRelease ? (
125+ < div className = "flex items-center justify-center h-32 bg-gray-800 rounded-lg" >
126+ < p className = "text-gray-400" > Loading latest code-scan release info...</ p >
127+ </ div >
128+ ) : releaseInfo ? (
129+ < LatestReleaseComponent releaseInfo = { releaseInfo } />
130+ ) : null }
131+ </ div >
132+ ) }
133+ < PageHeading isCentered > Changelog</ PageHeading >
51134 { ! ! builds && builds . map ( ( build , index ) => {
52135 return < BuildComponent build = { build } key = { index } />
53136 } ) }
0 commit comments