1+ import { useEffect , useState } from "react" ;
12import { useHealth } from "src/hooks" ;
23import { T } from "src/locale" ;
34
45export function SiteFooter ( ) {
5- const health = useHealth ( ) ;
6+ const health = useHealth ( ) ;
7+ const [ latestVersion , setLatestVersion ] = useState < string | null > ( null ) ;
8+ const [ isNewVersionAvailable , setIsNewVersionAvailable ] = useState ( false ) ;
69
7- const getVersion = ( ) => {
8- if ( ! health . data ) {
9- return "" ;
10- }
11- const v = health . data . version ;
12- return `v${ v . major } .${ v . minor } .${ v . revision } ` ;
13- } ;
10+ const getVersion = ( ) => {
11+ if ( ! health . data ) {
12+ return "" ;
13+ }
14+ const v = health . data . version ;
15+ return `v${ v . major } .${ v . minor } .${ v . revision } ` ;
16+ } ;
1417
15- return (
16- < footer className = "footer d-print-none py-3" >
17- < div className = "container-xl" >
18- < div className = "row text-center align-items-center flex-row-reverse" >
19- < div className = "col-lg-auto ms-lg-auto" >
20- < ul className = "list-inline list-inline-dots mb-0" >
21- < li className = "list-inline-item" >
22- < a
23- href = "https://github.com/NginxProxyManager/nginx-proxy-manager"
24- target = "_blank"
25- className = "link-secondary"
26- rel = "noopener"
27- >
28- < T id = "footer.github-fork" />
29- </ a >
30- </ li >
31- </ ul >
32- </ div >
33- < div className = "col-12 col-lg-auto mt-3 mt-lg-0" >
34- < ul className = "list-inline list-inline-dots mb-0" >
35- < li className = "list-inline-item" >
36- © 2025{ " " }
37- < a href = "https://jc21.com" rel = "noreferrer" target = "_blank" className = "link-secondary" >
38- jc21.com
39- </ a >
40- </ li >
41- < li className = "list-inline-item" >
42- Theme by{ " " }
43- < a href = "https://tabler.io" rel = "noreferrer" target = "_blank" className = "link-secondary" >
44- Tabler
45- </ a >
46- </ li >
47- < li className = "list-inline-item" >
48- < a
49- href = { `https://github.com/NginxProxyManager/nginx-proxy-manager/releases/tag/${ getVersion ( ) } ` }
50- className = "link-secondary"
51- target = "_blank"
52- rel = "noopener"
53- >
54- { " " }
55- { getVersion ( ) } { " " }
56- </ a >
57- </ li >
58- </ ul >
59- </ div >
60- </ div >
61- </ div >
62- </ footer >
63- ) ;
64- }
18+ const compareVersions = ( current : string , latest : string ) : boolean => {
19+ const cleanCurrent = current . replace ( / ^ v / , "" ) ;
20+ const cleanLatest = latest . replace ( / ^ v / , "" ) ;
21+
22+ const currentParts = cleanCurrent . split ( "." ) . map ( Number ) ;
23+ const latestParts = cleanLatest . split ( "." ) . map ( Number ) ;
24+
25+ for ( let i = 0 ; i < Math . max ( currentParts . length , latestParts . length ) ; i ++ ) {
26+ const curr = currentParts [ i ] || 0 ;
27+ const lat = latestParts [ i ] || 0 ;
28+
29+ if ( lat > curr ) return true ;
30+ if ( lat < curr ) return false ;
31+ }
32+ return false ;
33+ } ;
34+
35+ useEffect ( ( ) => {
36+ const checkForUpdates = async ( ) => {
37+ try {
38+ const response = await fetch (
39+ "https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest"
40+ ) ;
41+ if ( response . ok ) {
42+ const data = await response . json ( ) ;
43+ const latest = data . tag_name ;
44+ setLatestVersion ( latest ) ;
45+
46+ const currentVersion = "2.12.1" ;
47+ if ( currentVersion && compareVersions ( currentVersion , latest ) ) {
48+ setIsNewVersionAvailable ( true ) ;
49+ }
50+ }
51+ } catch ( error ) {
52+ console . debug ( "Could not check for updates:" , error ) ;
53+ }
54+ } ;
55+
56+ if ( health . data ) {
57+ checkForUpdates ( ) ;
58+ }
59+ } , [ health . data ] ) ;
60+
61+ return (
62+ < footer className = "footer d-print-none py-3" >
63+ < div className = "container-xl" >
64+ < div className = "row text-center align-items-center flex-row-reverse" >
65+ < div className = "col-lg-auto ms-lg-auto" >
66+ < ul className = "list-inline list-inline-dots mb-0" >
67+ < li className = "list-inline-item" >
68+ < a
69+ href = "https://github.com/NginxProxyManager/nginx-proxy-manager"
70+ target = "_blank"
71+ className = "link-secondary"
72+ rel = "noopener"
73+ >
74+ < T id = "footer.github-fork" />
75+ </ a >
76+ </ li >
77+ </ ul >
78+ </ div >
79+ < div className = "col-12 col-lg-auto mt-3 mt-lg-0" >
80+ < ul className = "list-inline list-inline-dots mb-0" >
81+ < li className = "list-inline-item" >
82+ © 2025{ " " }
83+ < a href = "https://jc21.com" rel = "noreferrer" target = "_blank" className = "link-secondary" >
84+ jc21.com
85+ </ a >
86+ </ li >
87+ < li className = "list-inline-item" >
88+ Theme by{ " " }
89+ < a href = "https://tabler.io" rel = "noreferrer" target = "_blank" className = "link-secondary" >
90+ Tabler
91+ </ a >
92+ </ li >
93+ < li className = "list-inline-item" >
94+ < a
95+ href = { `https://github.com/NginxProxyManager/nginx-proxy-manager/releases/tag/${ getVersion ( ) } ` }
96+ className = "link-secondary"
97+ target = "_blank"
98+ rel = "noopener"
99+ >
100+ { " " }
101+ { getVersion ( ) } { " " }
102+ </ a >
103+ </ li >
104+ { isNewVersionAvailable && latestVersion && (
105+ < li className = "list-inline-item" >
106+ < a
107+ href = { `https://github.com/NginxProxyManager/nginx-proxy-manager/releases/tag/${ latestVersion } ` }
108+ className = "link-warning fw-bold"
109+ target = "_blank"
110+ rel = "noopener"
111+ title = { `New version ${ latestVersion } is available` }
112+ >
113+ Update Available: ({ latestVersion } )
114+ </ a >
115+ </ li >
116+ ) }
117+ </ ul >
118+ </ div >
119+ </ div >
120+ </ div >
121+ </ footer >
122+ ) ;
123+ }
0 commit comments