@@ -2,7 +2,7 @@ import { SettingsPageHeader } from "@components/SettingsPageheader";
2
2
import { SettingsItem } from "./devices.$id.settings" ;
3
3
import { useLoaderData , useNavigate } from "react-router-dom" ;
4
4
import { Button , LinkButton } from "../components/Button" ;
5
- import { CLOUD_APP , DEVICE_API } from "../ui.config" ;
5
+ import { DEVICE_API } from "../ui.config" ;
6
6
import api from "../api" ;
7
7
import { LocalDevice } from "./devices.$id" ;
8
8
import { useDeviceUiNavigation } from "../hooks/useAppNavigation" ;
@@ -15,6 +15,7 @@ import { InputFieldWithLabel } from "../components/InputField";
15
15
import { SelectMenuBasic } from "../components/SelectMenuBasic" ;
16
16
import { SettingsSectionHeader } from "../components/SettingsSectionHeader" ;
17
17
import { isOnDevice } from "../main" ;
18
+ import { CloudState } from "./adopt" ;
18
19
19
20
export const loader = async ( ) => {
20
21
if ( isOnDevice ) {
@@ -36,38 +37,30 @@ export default function SettingsAccessIndexRoute() {
36
37
37
38
const [ isAdopted , setAdopted ] = useState ( false ) ;
38
39
const [ deviceId , setDeviceId ] = useState < string | null > ( null ) ;
39
- const [ cloudUrl , setCloudUrl ] = useState ( "" ) ;
40
- const [ cloudProviders , setCloudProviders ] = useState <
41
- { value : string ; label : string } [ ] | null
42
- > ( [ { value : "https://api.jetkvm.com" , label : "JetKVM Cloud" } ] ) ;
40
+ const [ cloudApiUrl , setCloudApiUrl ] = useState ( "" ) ;
41
+ const [ cloudAppUrl , setCloudAppUrl ] = useState ( "" ) ;
43
42
44
- // The default value is just there so it doesn't flicker while we fetch the default Cloud URL and available providers
45
- const [ selectedUrlOption , setSelectedUrlOption ] = useState < string > (
46
- "https://api.jetkvm.com" ,
47
- ) ;
48
-
49
- const [ defaultCloudUrl , setDefaultCloudUrl ] = useState < string > ( "" ) ;
50
-
51
- const syncCloudUrl = useCallback ( ( ) => {
52
- send ( "getCloudUrl" , { } , resp => {
53
- if ( "error" in resp ) return ;
54
- const url = resp . result as string ;
55
- setCloudUrl ( url ) ;
56
- // Check if the URL matches any predefined option
57
- if ( cloudProviders ?. some ( provider => provider . value === url ) ) {
58
- setSelectedUrlOption ( url ) ;
59
- } else {
60
- setSelectedUrlOption ( "custom" ) ;
61
- // setCustomCloudUrl(url);
62
- }
63
- } ) ;
64
- } , [ cloudProviders , send ] ) ;
43
+ // Use a simple string identifier for the selected provider
44
+ const [ selectedProvider , setSelectedProvider ] = useState < string > ( "jetkvm" ) ;
65
45
66
46
const getCloudState = useCallback ( ( ) => {
67
47
send ( "getCloudState" , { } , resp => {
68
48
if ( "error" in resp ) return console . error ( resp . error ) ;
69
- const cloudState = resp . result as { connected : boolean } ;
49
+ const cloudState = resp . result as CloudState ;
70
50
setAdopted ( cloudState . connected ) ;
51
+ setCloudApiUrl ( cloudState . url ) ;
52
+
53
+ if ( cloudState . appUrl ) setCloudAppUrl ( cloudState . appUrl ) ;
54
+
55
+ // Find if the API URL matches any of our predefined providers
56
+ const isAPIJetKVMProd = cloudState . url === "https://api.jetkvm.com" ;
57
+ const isAppJetKVMProd = cloudState . appUrl === "https://app.jetkvm.com" ;
58
+
59
+ if ( isAPIJetKVMProd && isAppJetKVMProd ) {
60
+ setSelectedProvider ( "jetkvm" ) ;
61
+ } else {
62
+ setSelectedProvider ( "custom" ) ;
63
+ }
71
64
} ) ;
72
65
} , [ send ] ) ;
73
66
@@ -88,42 +81,50 @@ export default function SettingsAccessIndexRoute() {
88
81
} ;
89
82
90
83
const onCloudAdoptClick = useCallback (
91
- ( url : string ) => {
84
+ ( cloudApiUrl : string , cloudAppUrl : string ) => {
92
85
if ( ! deviceId ) {
93
86
notifications . error ( "No device ID available" ) ;
94
87
return ;
95
88
}
96
89
97
- send ( "setCloudUrl" , { url } , resp => {
90
+ send ( "setCloudUrl" , { apiUrl : cloudApiUrl , appUrl : cloudAppUrl } , resp => {
98
91
if ( "error" in resp ) {
99
92
notifications . error (
100
93
`Failed to update cloud URL: ${ resp . error . data || "Unknown error" } ` ,
101
94
) ;
102
95
return ;
103
96
}
104
- syncCloudUrl ( ) ;
105
- notifications . success ( "Cloud URL updated successfully" ) ;
106
97
107
98
const returnTo = new URL ( window . location . href ) ;
108
99
returnTo . pathname = "/adopt" ;
109
100
returnTo . search = "" ;
110
101
returnTo . hash = "" ;
111
102
window . location . href =
112
- CLOUD_APP + "/signup?deviceId=" + deviceId + `&returnTo=${ returnTo . toString ( ) } ` ;
103
+ cloudAppUrl +
104
+ "/signup?deviceId=" +
105
+ deviceId +
106
+ `&returnTo=${ returnTo . toString ( ) } ` ;
113
107
} ) ;
114
108
} ,
115
- [ deviceId , syncCloudUrl , send ] ,
109
+ [ deviceId , send ] ,
116
110
) ;
117
111
118
- useEffect ( ( ) => {
119
- if ( ! defaultCloudUrl ) return ;
120
- setSelectedUrlOption ( defaultCloudUrl ) ;
121
- setCloudProviders ( [
122
- { value : defaultCloudUrl , label : "JetKVM Cloud" } ,
123
- { value : "custom" , label : "Custom" } ,
124
- ] ) ;
125
- } , [ defaultCloudUrl ] ) ;
112
+ // Handle provider selection change
113
+ const handleProviderChange = ( value : string ) => {
114
+ setSelectedProvider ( value ) ;
126
115
116
+ // If selecting a predefined provider, update both URLs
117
+ if ( value === "jetkvm" ) {
118
+ setCloudApiUrl ( "https://api.jetkvm.com" ) ;
119
+ setCloudAppUrl ( "https://app.jetkvm.com" ) ;
120
+ } else {
121
+ if ( cloudApiUrl || cloudAppUrl ) return ;
122
+ setCloudApiUrl ( "" ) ;
123
+ setCloudAppUrl ( "" ) ;
124
+ }
125
+ } ;
126
+
127
+ // Fetch device ID and cloud state on component mount
127
128
useEffect ( ( ) => {
128
129
getCloudState ( ) ;
129
130
@@ -133,18 +134,6 @@ export default function SettingsAccessIndexRoute() {
133
134
} ) ;
134
135
} , [ send , getCloudState ] ) ;
135
136
136
- useEffect ( ( ) => {
137
- send ( "getDefaultCloudUrl" , { } , resp => {
138
- if ( "error" in resp ) return console . error ( resp . error ) ;
139
- setDefaultCloudUrl ( resp . result as string ) ;
140
- } ) ;
141
- } , [ cloudProviders , syncCloudUrl , send ] ) ;
142
-
143
- useEffect ( ( ) => {
144
- if ( ! cloudProviders ?. length ) return ;
145
- syncCloudUrl ( ) ;
146
- } , [ cloudProviders , syncCloudUrl ] ) ;
147
-
148
137
return (
149
138
< div className = "space-y-4" >
150
139
< SettingsPageHeader
@@ -219,34 +208,42 @@ export default function SettingsAccessIndexRoute() {
219
208
>
220
209
< SelectMenuBasic
221
210
size = "SM"
222
- value = { selectedUrlOption }
223
- onChange = { e => {
224
- const value = e . target . value ;
225
- setSelectedUrlOption ( value ) ;
226
- } }
227
- options = { cloudProviders ?? [ ] }
211
+ value = { selectedProvider }
212
+ onChange = { e => handleProviderChange ( e . target . value ) }
213
+ options = { [
214
+ { value : "jetkvm" , label : "JetKVM Cloud" } ,
215
+ { value : "custom" , label : "Custom" } ,
216
+ ] }
228
217
/>
229
218
</ SettingsItem >
230
219
231
- { selectedUrlOption === "custom" && (
232
- < div className = "mt-4 flex items-end gap-x-2 space-y-4" >
233
- < InputFieldWithLabel
234
- size = "SM"
235
- label = "Custom Cloud URL"
236
- value = { cloudUrl }
237
- onChange = { e => setCloudUrl ( e . target . value ) }
238
- placeholder = "https://api.example.com"
239
- />
220
+ { selectedProvider === "custom" && (
221
+ < div className = "mt-4 space-y-4" >
222
+ < div className = "flex items-end gap-x-2" >
223
+ < InputFieldWithLabel
224
+ size = "SM"
225
+ label = "Cloud API URL"
226
+ value = { cloudApiUrl }
227
+ onChange = { e => setCloudApiUrl ( e . target . value ) }
228
+ placeholder = "https://api.example.com"
229
+ />
230
+ </ div >
231
+ < div className = "flex items-end gap-x-2" >
232
+ < InputFieldWithLabel
233
+ size = "SM"
234
+ label = "Cloud App URL"
235
+ value = { cloudAppUrl }
236
+ onChange = { e => setCloudAppUrl ( e . target . value ) }
237
+ placeholder = "https://app.example.com"
238
+ />
239
+ </ div >
240
240
</ div >
241
241
) }
242
242
</ >
243
243
) }
244
244
245
- { /*
246
- We do the harcoding here to avoid flickering when the default Cloud URL being fetched.
247
- I've tried to avoid harcoding api.jetkvm.com, but it's the only reasonable way I could think of to avoid flickering for now.
248
- */ }
249
- { selectedUrlOption === ( defaultCloudUrl || "https://api.jetkvm.com" ) && (
245
+ { /* Show security info for JetKVM Cloud */ }
246
+ { selectedProvider === "jetkvm" && (
250
247
< GridCard >
251
248
< div className = "flex items-start gap-x-4 p-4" >
252
249
< ShieldCheckIcon className = "mt-1 h-8 w-8 shrink-0 text-blue-600 dark:text-blue-500" />
@@ -295,7 +292,7 @@ export default function SettingsAccessIndexRoute() {
295
292
{ ! isAdopted ? (
296
293
< div className = "flex items-end gap-x-2" >
297
294
< Button
298
- onClick = { ( ) => onCloudAdoptClick ( cloudUrl ) }
295
+ onClick = { ( ) => onCloudAdoptClick ( cloudApiUrl , cloudAppUrl ) }
299
296
size = "SM"
300
297
theme = "primary"
301
298
text = "Adopt KVM to Cloud"
@@ -305,7 +302,7 @@ export default function SettingsAccessIndexRoute() {
305
302
< div >
306
303
< div className = "space-y-2" >
307
304
< p className = "text-sm text-slate-600 dark:text-slate-300" >
308
- Your device is adopted to JetKVM Cloud
305
+ Your device is adopted to the Cloud
309
306
</ p >
310
307
< div >
311
308
< Button
0 commit comments