Skip to content

Commit 588b87a

Browse files
Merge pull request #314 from timleavitt/fix-302-credential-prompt
fix #302: manage use of vscode.window.showInputBox
2 parents 06ff9b0 + 596392f commit 588b87a

File tree

3 files changed

+96
-5
lines changed

3 files changed

+96
-5
lines changed

src/extension.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ import {
7171
terminalWithDocker,
7272
notNull,
7373
currentFile,
74+
InputBoxManager,
7475
} from "./utils";
7576
import { ObjectScriptDiagnosticProvider } from "./providers/ObjectScriptDiagnosticProvider";
7677
import { DocumentRangeFormattingEditProvider } from "./providers/DocumentRangeFormattingEditProvider";
@@ -262,21 +263,23 @@ export function checkConnection(clearCookies = false, uri?: vscode.Uri): void {
262263
disableConnection(configName);
263264
}
264265
} else {
265-
vscode.window
266-
.showInputBox({
266+
InputBoxManager.showInputBox(
267+
{
267268
password: true,
268269
placeHolder: `Not Authorized. Enter password to connect as user '${username}' to ${connInfo}`,
269270
prompt: !api.externalServer ? "If no password is entered the connection will be disabled." : "",
270271
ignoreFocusOut: true,
271-
})
272-
.then((password) => {
272+
},
273+
(password) => {
273274
if (password) {
274275
workspaceState.update(configName + ":password", password);
275276
checkConnection(false, uri);
276277
} else if (!api.externalServer) {
277278
disableConnection(configName);
278279
}
279-
});
280+
},
281+
connInfo
282+
);
280283
}
281284
}, 1000);
282285
message = "Not Authorized";

src/utils/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ export function outputConsole(data: string[]): void {
1313
});
1414
}
1515

16+
import { InputBoxManager } from "./inputBoxManager";
17+
export { InputBoxManager };
18+
1619
// tslint:disable-next-line: interface-name
1720
export interface CurrentFile {
1821
name: string;

src/utils/inputBoxManager.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import vscode = require("vscode");
2+
3+
import { InputBoxOptions } from "vscode";
4+
5+
// Interface used internally to track queued input boxes
6+
interface InputBoxSpec {
7+
key?: string;
8+
options: InputBoxOptions;
9+
callback: (answer: string) => void;
10+
}
11+
12+
/**
13+
* Used in situations where multiple input boxes may be displayed in rapid succession
14+
* to allow the user to respond to them one at a time.
15+
*/
16+
export class InputBoxManager {
17+
/** Set to true if an input box is currently shown */
18+
private static shown = false;
19+
20+
/** Array of input boxes to show */
21+
private static specs = new Array<InputBoxSpec>();
22+
23+
/** Tracks the current key of the input box being shown (to make sure we don't re-queue it) */
24+
private static currentKey: string;
25+
26+
/**
27+
* Queues an input box to be shown via `vscode.window.showInputBox()`. If no input box is shown, will show immediately; otherwise,
28+
* will show once all previously-queued input boxes have resolved.
29+
* @param options Set of options for the input box
30+
* @param callback Function to run when the input box resolves. (If rejected, will move on to the next input box.)
31+
* @param key A unique identifier for the input box to be shown. If already present in the queue, will not be duplicated.
32+
*/
33+
public static showInputBox(options: InputBoxOptions, callback: (answer: string) => void, key?: string): void {
34+
const spec: InputBoxSpec = {
35+
options: options,
36+
callback: callback,
37+
};
38+
if (key) {
39+
// If a key was provided, make sure that we aren't already showing (and haven't already queued) an input box with that key.
40+
if (
41+
InputBoxManager.currentKey === key ||
42+
InputBoxManager.specs.find((spec) => {
43+
return spec.key === key;
44+
})
45+
) {
46+
return;
47+
}
48+
spec.key = key;
49+
}
50+
51+
// Add the input box to the list to show
52+
this.specs.push(spec);
53+
if (!this.shown) {
54+
this.shown = true;
55+
// If we aren't already showing an input box, show this one.
56+
this.next();
57+
}
58+
}
59+
60+
/** Shows the next input box in the queue, if any */
61+
private static next() {
62+
if (this.specs.length === 0) {
63+
// All done!
64+
this.shown = false;
65+
this.currentKey = undefined;
66+
return;
67+
}
68+
69+
// Get the next input box
70+
const spec = this.specs.shift();
71+
this.currentKey = spec.key;
72+
73+
// Show the input box, then execute the user-provided callback.
74+
// Always move on to the next input box afterward.
75+
vscode.window.showInputBox(spec.options).then(
76+
(result) => {
77+
spec.callback(result);
78+
InputBoxManager.next();
79+
},
80+
(ignored) => {
81+
InputBoxManager.next();
82+
}
83+
);
84+
}
85+
}

0 commit comments

Comments
 (0)