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,60 @@ 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 additionalData = user ?. additionalData ?? { } ;
39
+ const settings = additionalData . ideSettings ?? { } ;
40
+ settings . useDesktopIde = useDesktopIde ;
41
+ settings . defaultIde = defaultIde ;
42
+ settings . defaultDesktopIde = defaultDesktopIde ;
31
43
additionalData . ideSettings = settings ;
32
44
getGitpodService ( ) . server . trackEvent ( {
33
45
event : "ide_configuration_changed" ,
34
46
properties : {
35
47
useDesktopIde,
36
- defaultIde : value ,
48
+ defaultIde,
37
49
defaultDesktopIde : useDesktopIde ? defaultDesktopIde : undefined
38
50
} ,
39
- } ) ;
51
+ } ) . then ( ) . catch ( console . error ) ;
40
52
await getGitpodService ( ) . server . updateLoggedInUser ( { additionalData } ) ;
53
+ }
54
+
55
+ const [ defaultIde , setDefaultIde ] = useState < string > ( user ?. additionalData ?. ideSettings ?. defaultIde || "" ) ;
56
+ const actuallySetDefaultIde = async ( value : string ) => {
57
+ await updateUserIDEInfo ( defaultDesktopIde , value ) ;
41
58
setDefaultIde ( value ) ;
42
59
}
43
60
44
61
const [ defaultDesktopIde , setDefaultDesktopIde ] = useState < string > ( user ?. additionalData ?. ideSettings ?. defaultDesktopIde || "" ) ;
45
62
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 } ) ;
63
+ await updateUserIDEInfo ( value , defaultIde ) ;
59
64
setDefaultDesktopIde ( value ) ;
60
65
}
61
66
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
67
const [ ideOptions , setIdeOptions ] = useState < IDEOptions | undefined > ( undefined ) ;
83
68
useEffect ( ( ) => {
84
69
( async ( ) => {
85
70
const ideopts = await getGitpodService ( ) . server . getIDEOptions ( ) ;
71
+ ideopts . options [ DesktopNoneId ] = DesktopNone ;
86
72
setIdeOptions ( ideopts ) ;
87
73
if ( ! ( defaultIde ) ) {
88
74
setDefaultIde ( ideopts . defaultIde ) ;
@@ -117,51 +103,48 @@ export default function Preferences() {
117
103
118
104
return < div >
119
105
< 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 ) } />
106
+ { ideOptions && < >
107
+ { browserIdeOptions && < >
108
+ < h3 > Browser Editor</ h3 >
109
+ < p className = "text-base text-gray-500 dark:text-gray-400" > Choose the default editor for opening workspaces in the browser.</ p >
110
+ < div className = "my-4 gap-4 flex flex-wrap" >
111
+ {
112
+ browserIdeOptions . map ( ( [ id , option ] ) => {
113
+ const selected = defaultIde === id ;
114
+ const onSelect = ( ) => actuallySetDefaultIde ( id ) ;
115
+ return renderIdeOption ( option , selected , onSelect ) ;
116
+ } )
117
+ }
144
118
</ 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 >
119
+ { ideOptions . options [ defaultIde ] ?. notes &&
120
+ < InfoBox className = "my-5 max-w-2xl" > < ul >
121
+ { ideOptions . options [ defaultIde ] . notes ?. map ( ( x , idx ) => < li className = { idx > 0 ? "mt-2" : "" } > { x } </ li > ) }
122
+ </ ul > </ InfoBox >
123
+ }
124
+ </ > }
125
+ { desktopIdeOptions && < >
126
+ < h3 className = "mt-12" > Desktop Editor</ h3 >
127
+ < p className = "text-base text-gray-500 dark:text-gray-400" > Optionally, choose the default desktop editor for opening workspaces.</ p >
128
+ < div className = "my-4 gap-4 flex flex-wrap" >
129
+ {
130
+ desktopIdeOptions . map ( ( [ id , option ] ) => {
131
+ let selected = defaultDesktopIde === id ;
132
+ const onSelect = ( ) => actuallySetDefaultDesktopIde ( id ) ;
133
+ if ( id === DesktopNoneId ) {
134
+ option . logo = isDark ? IDENoneDark : IDENone
135
+ }
136
+ return renderIdeOption ( option , selected , onSelect ) ;
137
+ } )
160
138
}
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
- </ > }
139
+ </ div >
140
+ { ideOptions . options [ defaultDesktopIde ] ?. notes &&
141
+ < InfoBox className = "my-5 max-w-2xl" > < ul >
142
+ { ideOptions . options [ defaultDesktopIde ] . notes ?. map ( ( x , idx ) => < li className = { idx > 0 ? "mt-2" : "" } > { x } </ li > ) }
143
+ </ ul > </ InfoBox >
144
+ }
145
+ < p className = "text-left w-full text-gray-500" >
146
+ 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 >
147
+ </ p >
165
148
</ > }
166
149
</ > }
167
150
< h3 className = "mt-12" > Theme</ h3 >
@@ -201,6 +184,7 @@ export default function Preferences() {
201
184
}
202
185
203
186
function orderedIdeOptions ( ideOptions : IDEOptions , type : "browser" | "desktop" ) {
187
+ // TODO: Maybe convert orderKey to number before sort?
204
188
return Object . entries ( ideOptions . options )
205
189
. filter ( ( [ _ , x ] ) => x . type === type && ! x . hidden )
206
190
. sort ( ( a , b ) => {
@@ -216,7 +200,7 @@ function renderIdeOption(option: IDEOption, selected: boolean, onSelect: () => v
216
200
< img className = "w-16 filter-grayscale self-center"
217
201
src = { option . logo } alt = "logo" />
218
202
</ 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 > : < > </ > }
203
+ { 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
204
</ SelectableCard > ;
221
205
222
206
if ( option . tooltip ) {
0 commit comments