@@ -8,42 +8,85 @@ import { Remote } from "./remote"
8
8
import { Storage } from "./storage"
9
9
import { OpenableTreeItem } from "./workspacesProvider"
10
10
11
- // maybeAskUrl asks the user for the URL if it was not provided and normalizes
12
- // the returned URL.
13
- export async function maybeAskUrl (
14
- providedUrl : string | undefined | null ,
15
- lastUsedUrl ?: string ,
16
- ) : Promise < string | undefined > {
17
- let url =
18
- providedUrl ||
19
- ( await vscode . window . showInputBox ( {
20
- title : "Coder URL" ,
21
- prompt : "Enter the URL of your Coder deployment." ,
22
- placeHolder : "https://example.coder.com" ,
23
- value : lastUsedUrl ,
24
- } ) )
25
- if ( ! url ) {
26
- return undefined
27
- }
28
- if ( ! url . startsWith ( "http://" ) && ! url . startsWith ( "https://" ) ) {
29
- // Default to HTTPS if not provided!
30
- // https://github.com/coder/vscode-coder/issues/44
31
- url = "https://" + url
32
- }
33
- while ( url . endsWith ( "/" ) ) {
34
- url = url . substring ( 0 , url . length - 1 )
35
- }
36
- return url
37
- }
38
-
39
11
export class Commands {
40
12
public constructor (
41
13
private readonly vscodeProposed : typeof vscode ,
42
14
private readonly storage : Storage ,
43
15
) { }
44
16
17
+ /**
18
+ * Ask the user for the URL, letting them choose from a list of recent URLs or
19
+ * CODER_URL or enter a new one. Undefined means the user aborted.
20
+ */
21
+ private askURL ( selection ?: string ) : Promise < string | undefined > {
22
+ const quickPick = vscode . window . createQuickPick ( )
23
+ quickPick . value = selection || process . env . CODER_URL || ""
24
+ quickPick . placeholder = "https://example.coder.com" ,
25
+ quickPick . title = "Enter the URL of your Coder deployment." ,
26
+
27
+ // Initial items.
28
+ quickPick . items = this . storage . withUrlHistory ( process . env . CODER_URL )
29
+ . map ( ( url ) => ( {
30
+ alwaysShow : true ,
31
+ label : url
32
+ } ) )
33
+
34
+ // Quick picks do not allow arbitrary values, so we add the value itself as
35
+ // an option in case the user wants to connect to something that is not in
36
+ // the list.
37
+ quickPick . onDidChangeValue ( ( value ) => {
38
+ quickPick . items = this . storage . withUrlHistory ( process . env . CODER_URL , value )
39
+ . map ( ( url ) => ( {
40
+ alwaysShow : true ,
41
+ label : url ,
42
+ } ) )
43
+ } )
44
+
45
+ quickPick . show ( )
46
+
47
+ return new Promise < string | undefined > ( ( resolve ) => {
48
+ quickPick . onDidHide ( ( ) => resolve ( undefined ) )
49
+ quickPick . onDidChangeSelection ( ( selected ) => resolve ( selected [ 0 ] ?. label ) )
50
+ } )
51
+ }
52
+
53
+ /**
54
+ * Ask the user for the URL if it was not provided, letting them choose from a
55
+ * list of recent URLs or CODER_URL or enter a new one, and normalizes the
56
+ * returned URL. Undefined means the user aborted.
57
+ */
58
+ public async maybeAskUrl (
59
+ providedUrl : string | undefined | null ,
60
+ lastUsedUrl ?: string ,
61
+ ) : Promise < string | undefined > {
62
+ let url = providedUrl || await askURL ( lastUsedUrl )
63
+ if ( ! url ) { // User aborted.
64
+ return undefined
65
+ }
66
+
67
+ // Normalize URL.
68
+ if ( ! url . startsWith ( "http://" ) && ! url . startsWith ( "https://" ) ) {
69
+ // Default to HTTPS if not provided!
70
+ // https://github.com/coder/vscode-coder/issues/44
71
+ url = "https://" + url
72
+ }
73
+ while ( url . endsWith ( "/" ) ) {
74
+ url = url . substring ( 0 , url . length - 1 )
75
+ }
76
+ return url
77
+ }
78
+
79
+ /**
80
+ * Log into the provided deployment. If the deployment URL is not specified,
81
+ * ask for it first with a menu showing recent URLs and CODER_URL, if set.
82
+ */
45
83
public async login ( ...args : string [ ] ) : Promise < void > {
46
- const url = await maybeAskUrl ( args [ 0 ] )
84
+ const url = await this . maybeAskUrl ( args [ 0 ] )
85
+ if ( ! url ) {
86
+ vscode . window . showWarningMessage ( "Aborting login because no URL was provided." )
87
+ return
88
+ }
89
+
47
90
let token : string | undefined = args . length >= 2 ? args [ 1 ] : undefined
48
91
if ( ! token ) {
49
92
const opened = await vscode . env . openExternal ( vscode . Uri . parse ( `${ url } /cli-auth` ) )
@@ -91,6 +134,7 @@ export class Commands {
91
134
} )
92
135
}
93
136
if ( ! token ) {
137
+ vscode . window . showWarningMessage ( "Aborting login because no token was provided." )
94
138
return
95
139
}
96
140
0 commit comments