6
6
7
7
import { IDEOption , IDEOptions } from "@gitpod/gitpod-protocol/lib/ide-protocol" ;
8
8
import { useContext , useEffect , useState } from "react" ;
9
- import CheckBox from "../components/CheckBox" ;
10
9
import InfoBox from "../components/InfoBox" ;
11
10
import { PageWithSubMenu } from "../components/PageWithSubMenu" ;
12
11
import PillLabel from "../components/PillLabel" ;
@@ -16,73 +15,61 @@ import { getGitpodService } from "../service/service";
16
15
import { ThemeContext } from "../theme-context" ;
17
16
import { UserContext } from "../user-context" ;
18
17
import settingsMenu from "./settings-menu" ;
18
+ import IDENone from '../icons/IDENone.svg' ;
19
+ import IDENoneDark from '../icons/IDENoneDark.svg' ;
19
20
20
21
type Theme = 'light' | 'dark' | 'system' ;
21
22
23
+ const DesktopNoneId = "none" ;
24
+ const DesktopNone : IDEOption = {
25
+ "image" : "" ,
26
+ "logo" : IDENone ,
27
+ "orderKey" : "-1" ,
28
+ "title" : "None" ,
29
+ "type" : "desktop"
30
+ } ;
31
+
22
32
export default function Preferences ( ) {
23
33
const { user } = useContext ( UserContext ) ;
24
- const { setIsDark } = useContext ( ThemeContext ) ;
25
-
26
- const [ defaultIde , setDefaultIde ] = useState < string > ( user ?. additionalData ?. ideSettings ?. defaultIde || "" ) ;
27
- const actuallySetDefaultIde = async ( value : string ) => {
28
- const additionalData = user ?. additionalData || { } ;
29
- const settings = additionalData . ideSettings || { } ;
30
- settings . defaultIde = value ;
34
+ const { setIsDark, isDark } = useContext ( ThemeContext ) ;
35
+
36
+ const updateUserIDEInfo = async ( defaultDesktopIde : string , defaultIde : string ) => {
37
+ const useDesktopIde = defaultDesktopIde !== DesktopNoneId ;
38
+ const desktopIde = useDesktopIde ? defaultDesktopIde : undefined ;
39
+ const additionalData = user ?. additionalData ?? { } ;
40
+ const settings = additionalData . ideSettings ?? { } ;
41
+ settings . useDesktopIde = useDesktopIde ;
42
+ settings . defaultIde = defaultIde ;
43
+ settings . defaultDesktopIde = desktopIde ;
31
44
additionalData . ideSettings = settings ;
32
45
getGitpodService ( ) . server . trackEvent ( {
33
46
event : "ide_configuration_changed" ,
34
47
properties : {
35
48
useDesktopIde,
36
- defaultIde : value ,
37
- defaultDesktopIde : useDesktopIde ? defaultDesktopIde : undefined
49
+ defaultIde,
50
+ defaultDesktopIde : desktopIde
38
51
} ,
39
- } ) ;
52
+ } ) . then ( ) . catch ( console . error ) ;
40
53
await getGitpodService ( ) . server . updateLoggedInUser ( { additionalData } ) ;
54
+ }
55
+
56
+ const [ defaultIde , setDefaultIde ] = useState < string > ( user ?. additionalData ?. ideSettings ?. defaultIde || "" ) ;
57
+ const actuallySetDefaultIde = async ( value : string ) => {
58
+ await updateUserIDEInfo ( defaultDesktopIde , value ) ;
41
59
setDefaultIde ( value ) ;
42
60
}
43
61
44
- const [ defaultDesktopIde , setDefaultDesktopIde ] = useState < string > ( user ?. additionalData ?. ideSettings ?. defaultDesktopIde || "" ) ;
62
+ const [ defaultDesktopIde , setDefaultDesktopIde ] = useState < string > ( ( user ?. additionalData ?. ideSettings ?. useDesktopIde && user ?. additionalData ?. ideSettings ?. defaultDesktopIde ) || DesktopNoneId ) ;
45
63
const actuallySetDefaultDesktopIde = async ( value : string ) => {
46
- const additionalData = user ?. additionalData || { } ;
47
- const settings = additionalData . ideSettings || { } ;
48
- settings . defaultDesktopIde = value ;
49
- additionalData . ideSettings = settings ;
50
- getGitpodService ( ) . server . trackEvent ( {
51
- event : "ide_configuration_changed" ,
52
- properties : {
53
- useDesktopIde,
54
- defaultIde,
55
- defaultDesktopIde : value
56
- } ,
57
- } ) ;
58
- await getGitpodService ( ) . server . updateLoggedInUser ( { additionalData } ) ;
64
+ await updateUserIDEInfo ( value , defaultIde ) ;
59
65
setDefaultDesktopIde ( value ) ;
60
66
}
61
67
62
- const [ useDesktopIde , setUseDesktopIde ] = useState < boolean > ( user ?. additionalData ?. ideSettings ?. useDesktopIde || false ) ;
63
- const actuallySetUseDesktopIde = async ( value : boolean ) => {
64
- const additionalData = user ?. additionalData || { } ;
65
- const settings = additionalData . ideSettings || { } ;
66
- settings . useDesktopIde = value ;
67
- // Make sure that default desktop IDE is set even when the user did not explicitly select one.
68
- settings . defaultDesktopIde = defaultDesktopIde ;
69
- additionalData . ideSettings = settings ;
70
- getGitpodService ( ) . server . trackEvent ( {
71
- event : "ide_configuration_changed" ,
72
- properties : {
73
- useDesktopIde : value ,
74
- defaultIde,
75
- defaultDesktopIde : value ? defaultDesktopIde : undefined
76
- } ,
77
- } ) ;
78
- await getGitpodService ( ) . server . updateLoggedInUser ( { additionalData } ) ;
79
- setUseDesktopIde ( value ) ;
80
- }
81
-
82
68
const [ ideOptions , setIdeOptions ] = useState < IDEOptions | undefined > ( undefined ) ;
83
69
useEffect ( ( ) => {
84
70
( async ( ) => {
85
71
const ideopts = await getGitpodService ( ) . server . getIDEOptions ( ) ;
72
+ ideopts . options [ DesktopNoneId ] = DesktopNone ;
86
73
setIdeOptions ( ideopts ) ;
87
74
if ( ! ( defaultIde ) ) {
88
75
setDefaultIde ( ideopts . defaultIde ) ;
@@ -117,51 +104,48 @@ export default function Preferences() {
117
104
118
105
return < div >
119
106
< PageWithSubMenu subMenu = { settingsMenu } title = 'Preferences' subtitle = 'Configure user preferences.' >
120
- { ideOptions && browserIdeOptions && < >
121
- < h3 > Editor</ h3 >
122
- < p className = "text-base text-gray-500 dark:text-gray-400" > Choose which IDE you want to use.</ p >
123
- < div className = "my-4 space-x-4 flex" >
124
- {
125
- browserIdeOptions . map ( ( [ id , option ] ) => {
126
- const selected = defaultIde === id ;
127
- const onSelect = ( ) => actuallySetDefaultIde ( id ) ;
128
- return renderIdeOption ( option , selected , onSelect ) ;
129
- } )
130
- }
131
- </ div >
132
- { ideOptions . options [ defaultIde ] . notes &&
133
- < InfoBox className = "my-5 max-w-2xl" > < ul >
134
- { ideOptions . options [ defaultIde ] . notes ?. map ( ( x , idx ) => < li className = { idx > 0 ? "mt-2" : "" } > { x } </ li > ) }
135
- </ ul > </ InfoBox >
136
- }
137
- { desktopIdeOptions && desktopIdeOptions . length > 0 && < >
138
- < div className = "mt-4 space-x-4 flex" >
139
- < CheckBox
140
- title = { < div > Open in Desktop IDE < PillLabel type = "warn" className = "font-semibold mt-2 py-0.5 px-2 self-center" > Beta</ PillLabel > </ div > }
141
- desc = "Choose whether you would like to open your workspace in a desktop IDE instead."
142
- checked = { useDesktopIde }
143
- onChange = { ( evt ) => actuallySetUseDesktopIde ( evt . target . checked ) } />
107
+ { ideOptions && < >
108
+ { browserIdeOptions && < >
109
+ < h3 > Browser Editor</ h3 >
110
+ < p className = "text-base text-gray-500 dark:text-gray-400" > Choose the default editor for opening workspaces in the browser.</ p >
111
+ < div className = "my-4 gap-4 flex flex-wrap" >
112
+ {
113
+ browserIdeOptions . map ( ( [ id , option ] ) => {
114
+ const selected = defaultIde === id ;
115
+ const onSelect = ( ) => actuallySetDefaultIde ( id ) ;
116
+ return renderIdeOption ( option , selected , onSelect ) ;
117
+ } )
118
+ }
144
119
</ div >
145
- { useDesktopIde && < >
146
- < div className = "my-4 space-x-4 flex" >
147
- {
148
- desktopIdeOptions . map ( ( [ id , option ] ) => {
149
- const selected = defaultDesktopIde === id ;
150
- const onSelect = ( ) => actuallySetDefaultDesktopIde ( id ) ;
151
- return renderIdeOption ( option , selected , onSelect ) ;
152
- } )
153
- }
154
- </ div >
155
-
156
- { ideOptions . options [ defaultDesktopIde ] . notes &&
157
- < InfoBox className = "my-5 max-w-2xl" > < ul >
158
- { ideOptions . options [ defaultDesktopIde ] . notes ?. map ( ( x , idx ) => < li className = { idx > 0 ? "mt-2" : "" } > { x } </ li > ) }
159
- </ ul > </ InfoBox >
120
+ { ideOptions . options [ defaultIde ] ?. notes &&
121
+ < InfoBox className = "my-5 max-w-2xl" > < ul >
122
+ { ideOptions . options [ defaultIde ] . notes ?. map ( ( x , idx ) => < li className = { idx > 0 ? "mt-2" : "" } > { x } </ li > ) }
123
+ </ ul > </ InfoBox >
124
+ }
125
+ </ > }
126
+ { desktopIdeOptions && < >
127
+ < h3 className = "mt-12" > Desktop Editor</ h3 >
128
+ < p className = "text-base text-gray-500 dark:text-gray-400" > Optionally, choose the default desktop editor for opening workspaces.</ p >
129
+ < div className = "my-4 gap-4 flex flex-wrap" >
130
+ {
131
+ desktopIdeOptions . map ( ( [ id , option ] ) => {
132
+ const selected = defaultDesktopIde === id ;
133
+ const onSelect = ( ) => actuallySetDefaultDesktopIde ( id ) ;
134
+ if ( id === DesktopNoneId ) {
135
+ option . logo = isDark ? IDENoneDark : IDENone
136
+ }
137
+ return renderIdeOption ( option , selected , onSelect ) ;
138
+ } )
160
139
}
161
- < p className = "text-left w-full text-gray-500" >
162
- The < strong > JetBrains desktop IDEs</ strong > are currently in beta. < a href = "https://github.com/gitpod-io/gitpod/issues/6576" target = "gitpod-feedback-issue" rel = "noopener" className = "gp-link" > Send feedback</ a > · < a href = "https://www.gitpod.io/docs/integrations/jetbrains" target = "_blank" rel = "noopener noreferrer" className = "gp-link" > Documentation</ a >
163
- </ p >
164
- </ > }
140
+ </ div >
141
+ { ideOptions . options [ defaultDesktopIde ] ?. notes &&
142
+ < InfoBox className = "my-5 max-w-2xl" > < ul >
143
+ { ideOptions . options [ defaultDesktopIde ] . notes ?. map ( ( x , idx ) => < li className = { idx > 0 ? "mt-2" : "" } > { x } </ li > ) }
144
+ </ ul > </ InfoBox >
145
+ }
146
+ < p className = "text-left w-full text-gray-500" >
147
+ The < strong > JetBrains desktop IDEs</ strong > are currently in beta. < a href = "https://github.com/gitpod-io/gitpod/issues/6576" target = "gitpod-feedback-issue" rel = "noopener" className = "gp-link" > Send feedback</ a > · < a href = "https://www.gitpod.io/docs/integrations/jetbrains" target = "_blank" rel = "noopener noreferrer" className = "gp-link" > Documentation</ a >
148
+ </ p >
165
149
</ > }
166
150
</ > }
167
151
< h3 className = "mt-12" > Theme</ h3 >
@@ -201,6 +185,7 @@ export default function Preferences() {
201
185
}
202
186
203
187
function orderedIdeOptions ( ideOptions : IDEOptions , type : "browser" | "desktop" ) {
188
+ // TODO: Maybe convert orderKey to number before sort?
204
189
return Object . entries ( ideOptions . options )
205
190
. filter ( ( [ _ , x ] ) => x . type === type && ! x . hidden )
206
191
. sort ( ( a , b ) => {
@@ -216,7 +201,7 @@ function renderIdeOption(option: IDEOption, selected: boolean, onSelect: () => v
216
201
< img className = "w-16 filter-grayscale self-center"
217
202
src = { option . logo } alt = "logo" />
218
203
</ div >
219
- { option . label ? < div className = { `font-semibold text-sm ${ selected ? 'text-green-500' : 'text-gray-500 dark:text-gray-400' } uppercase mt-2 ml-2 px-3 py-1 self-center` } > { option . label } </ div > : < > </ > }
204
+ { option . label ? < div className = { `font-semibold text-sm ${ selected ? 'text-green-500' : 'text-gray-500 dark:text-gray-400' } uppercase mt-2 px-3 py-1 self-center` } > { option . label } </ div > : < > </ > }
220
205
</ SelectableCard > ;
221
206
222
207
if ( option . tooltip ) {
0 commit comments