@@ -3,8 +3,11 @@ import { compare, major, minor } from "semver";
33
44const FADERPUNK_VENDOR_ID = 0xf569 ;
55const FADERPUNK_PRODUCT_ID = 0x1 ;
6- const FIRMWARE_LATEST_VERSION = __FIRMWARE_LATEST_VERSION__ ;
7- const VERSION_PATH = `/${ major ( FIRMWARE_LATEST_VERSION ) } .${ minor ( FIRMWARE_LATEST_VERSION ) } /` ;
6+ const BUILD_TIME_VERSION = __FIRMWARE_LATEST_VERSION__ ;
7+
8+ function versionPath ( version : string ) {
9+ return `/${ major ( version ) } .${ minor ( version ) } /` ;
10+ }
811
912type State =
1013 | { status : "idle" }
@@ -19,14 +22,27 @@ type State =
1922
2023export default function App ( ) {
2124 const [ state , setState ] = useState < State > ( { status : "idle" } ) ;
25+ const [ latestVersion , setLatestVersion ] = useState ( BUILD_TIME_VERSION ) ;
2226 const webUsbSupported = ! ! navigator . usb ;
2327
28+ // Fetch latest firmware version from version.json (falls back to build-time constant)
29+ useEffect ( ( ) => {
30+ fetch ( "/version.json" )
31+ . then ( ( r ) => ( r . ok ? r . json ( ) : Promise . reject ( ) ) )
32+ . then ( ( data : { firmware : string } ) => {
33+ if ( data . firmware ) setLatestVersion ( data . firmware ) ;
34+ } )
35+ . catch ( ( ) => { } ) ;
36+ } , [ ] ) ;
37+
2438 // Redirect hash routes to the versioned deployment
2539 useEffect ( ( ) => {
2640 if ( window . location . hash ) {
27- window . location . replace ( VERSION_PATH + window . location . hash ) ;
41+ window . location . replace (
42+ versionPath ( latestVersion ) + window . location . hash ,
43+ ) ;
2844 }
29- } , [ ] ) ;
45+ } , [ latestVersion ] ) ;
3046
3147 async function connectAndRedirect ( ) {
3248 setState ( { status : "connecting" } ) ;
@@ -57,7 +73,7 @@ export default function App() {
5773 // Determine target path for the matching configurator
5874 let configuratorPath : string ;
5975
60- if ( compare ( deviceVersion , FIRMWARE_LATEST_VERSION ) > 0 ) {
76+ if ( compare ( deviceVersion , latestVersion ) > 0 ) {
6177 // Device version is newer than latest stable → beta
6278 configuratorPath = "/beta/" ;
6379 } else if ( compare ( deviceVersion , "1.7.0" ) < 0 ) {
@@ -68,7 +84,7 @@ export default function App() {
6884 }
6985
7086 // Firmware is outdated → show update choice
71- if ( compare ( deviceVersion , FIRMWARE_LATEST_VERSION ) < 0 ) {
87+ if ( compare ( deviceVersion , latestVersion ) < 0 ) {
7288 setState ( {
7389 status : "update-available" ,
7490 currentVersion : deviceVersion ,
@@ -142,13 +158,13 @@ export default function App() {
142158
143159 < div className = "mt-4 flex items-center justify-between gap-4" >
144160 < a
145- href = { VERSION_PATH + "#/troubleshooting" }
161+ href = { versionPath ( latestVersion ) + "#/troubleshooting" }
146162 className = "cursor-pointer text-center text-gray-400 underline hover:text-[#d4d4d8]"
147163 >
148164 Trouble connecting?
149165 </ a >
150166 < a
151- href = { VERSION_PATH + "#/about" }
167+ href = { versionPath ( latestVersion ) + "#/about" }
152168 className = "cursor-pointer text-center text-gray-400 underline hover:text-[#d4d4d8]"
153169 >
154170 What is this?
@@ -177,14 +193,15 @@ export default function App() {
177193 </ span >
178194 . Version{ " " }
179195 < span className = "text-pink-fp font-semibold" >
180- v{ FIRMWARE_LATEST_VERSION }
196+ v{ latestVersion }
181197 </ span > { " " }
182198 is available.
183199 </ p >
184200 < div className = "flex justify-center gap-3" >
185201 < button
186202 onClick = { ( ) => {
187- window . location . href = VERSION_PATH + "#/update" ;
203+ window . location . href =
204+ versionPath ( latestVersion ) + "#/update" ;
188205 } }
189206 className = "cursor-pointer rounded-sm bg-white px-6 py-2 text-xs font-semibold text-black transition-opacity hover:opacity-90"
190207 >
0 commit comments