Skip to content

Commit bb93ca8

Browse files
authored
Present first view according to user setting (#189)
* Present first view according to user setting Signed-off-by: Rome Li <[email protected]> * Subscribe to less events Signed-off-by: Rome Li <[email protected]>
1 parent ff82e45 commit bb93ca8

File tree

6 files changed

+147
-6
lines changed

6 files changed

+147
-6
lines changed

package.json

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,30 @@
6161
"command": "java.gettingStarted",
6262
"title": "Java: Getting Started"
6363
}
64-
]
64+
],
65+
"configuration":{
66+
"title": "Java Extension Pack",
67+
"properties": {
68+
"java.help.firstView": {
69+
"type": [
70+
"string"
71+
],
72+
"enum": [
73+
"auto",
74+
"overview",
75+
"gettingStarted"
76+
],
77+
"enumDescriptions": [
78+
"Automatically pick the first experience view",
79+
"Present the Java Overview page",
80+
"Present the Java Getting Started page"
81+
],
82+
"default": "auto",
83+
"description": "Sets the default view which is presented during the first use.",
84+
"scope": "window"
85+
}
86+
}
87+
}
6588
},
6689
"scripts": {
6790
"vscode:prepublish": "npm run build",

src/extension.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,16 @@ import { initialize as initUtils } from "./utils";
88
import { initialize as initCommands } from "./commands";
99
import { initialize as initRecommendations } from "./recommendation";
1010
import { initialize as initMisc, showReleaseNotesOnStart } from "./misc";
11-
import { showOverviewPageOnActivation, OverviewViewSerializer } from "./overview";
11+
import { OverviewViewSerializer, showOverviewPageOnActivation } from "./overview";
1212
import { validateJavaRuntime, JavaRuntimeViewSerializer } from "./java-runtime";
1313
import { JavaGettingStartedViewSerializer } from "./getting-started";
14+
import { scheduleAction } from "./utils/scheduler";
15+
16+
enum ViewType {
17+
Auto = "auto",
18+
Overview = "overview",
19+
GettingStarted = "gettingStarted",
20+
}
1421

1522
export async function activate(context: vscode.ExtensionContext) {
1623
initializeTelemetry(context);
@@ -27,14 +34,40 @@ async function initializeExtension(operationId: string, context: vscode.Extensio
2734
context.subscriptions.push(vscode.window.registerWebviewPanelSerializer("java.runtime", new JavaRuntimeViewSerializer()));
2835
context.subscriptions.push(vscode.window.registerWebviewPanelSerializer("java.gettingStarted", new JavaGettingStartedViewSerializer()));
2936

30-
await showOverviewPageOnActivation(context);
31-
await showReleaseNotesOnStart(context);
37+
scheduleAction("showFirstView", true).then(() => {
38+
presentFirstView(context);
39+
});
40+
41+
scheduleAction("showReleaseNotes").then(() => {
42+
showReleaseNotesOnStart(context);
43+
});
3244

3345
if (!await validateJavaRuntime()) {
34-
vscode.commands.executeCommand("java.runtime");
46+
scheduleAction("showJdkState", true, true).then(() => {
47+
vscode.commands.executeCommand("java.runtime");
48+
});
49+
}
50+
}
51+
52+
async function presentFirstView(context: vscode.ExtensionContext) {
53+
const config = vscode.workspace.getConfiguration("java.help");
54+
const firstView = config.get("firstView");
55+
if (firstView === ViewType.GettingStarted) {
56+
await showGettingStartedView(context);
57+
} else {
58+
await showOverviewPageOnActivation(context);
3559
}
3660
}
3761

62+
async function showGettingStartedView(context: vscode.ExtensionContext, isForce: boolean = false) {
63+
if (!!context.globalState.get("isGettingStartedPresented")) {
64+
return;
65+
}
66+
67+
await vscode.commands.executeCommand("java.gettingStarted");
68+
context.globalState.update("isGettingStartedPresented", true);
69+
}
70+
3871
function initializeTelemetry(context: vscode.ExtensionContext) {
3972
const ext = vscode.extensions.getExtension("vscjava.vscode-java-pack");
4073
const packageInfo = ext ? ext.packageJSON : undefined;

src/java-runtime/assets/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ declare function acquireVsCodeApi(): any;
5858
const vscode = acquireVsCodeApi();
5959

6060
function requestJdkInfo(jdkVersion: string, jvmImpl: string) {
61-
console.log(`request ${jdkVersion} ${jvmImpl}`);
6261
vscode.postMessage({
6362
command: "requestJdkInfo",
6463
jdkVersion: jdkVersion,

src/utils/idle.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
import * as vscode from "vscode";
5+
6+
// in milliseconds
7+
let timeElapsed: number = 0;
8+
const INTERVAL = 1000;
9+
// reference - https://medium.com/@slhenty/ui-response-times-acec744f3157
10+
// 5s is when users start to lose focus
11+
const IDLE_THRESHOLD = 5000;
12+
13+
export function initialize(context: vscode.ExtensionContext) {
14+
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(vscodeEventHandler)); // switching editor
15+
context.subscriptions.push(vscode.window.onDidChangeTextEditorSelection(vscodeEventHandler)); // change cursor position
16+
context.subscriptions.push(vscode.window.onDidChangeTextEditorVisibleRanges(vscodeEventHandler)); // scrolling
17+
18+
setInterval(timerEventHandler, INTERVAL);
19+
}
20+
21+
function vscodeEventHandler() {
22+
timeElapsed = 0;
23+
}
24+
25+
function timerEventHandler() {
26+
timeElapsed += INTERVAL;
27+
if (timeElapsed >= IDLE_THRESHOLD) {
28+
timeElapsed = 0;
29+
_onIdle.fire();
30+
}
31+
}
32+
33+
const _onIdle: vscode.EventEmitter<void> = new vscode.EventEmitter;
34+
export const onIdle: vscode.Event<void> = _onIdle.event;

src/utils/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@
44
import * as vscode from "vscode";
55
import { readFile as fsReadFile } from "fs";
66
import * as util from "util";
7+
import { initialize as initializeIdle } from "./idle";
8+
import { initialize as initializeScheduler } from "./scheduler";
79

810
const readFile = util.promisify(fsReadFile);
911

1012
let extensionContext: vscode.ExtensionContext;
1113

1214
export function initialize(context: vscode.ExtensionContext) {
1315
extensionContext = context;
16+
initializeIdle(context);
17+
initializeScheduler(context);
1418
}
1519

1620
export function getExtensionContext() {

src/utils/scheduler.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
import * as vscode from "vscode";
5+
import { onIdle } from "./idle";
6+
import * as _ from "lodash";
7+
8+
interface Action {
9+
name: string;
10+
resolve: (name: string) => void;
11+
}
12+
13+
const actionQueue: Action[] = [];
14+
const pastActions: string[] = [];
15+
16+
export function initialize(context: vscode.ExtensionContext) {
17+
context.subscriptions.push(onIdle(() => idleHandler()));
18+
}
19+
20+
// This is to queue the actions that need attention from users. One thing at a time, only on idle.
21+
export function scheduleAction(name: string, isImmediate: boolean = false, isOneTime: boolean = false): Promise<string> {
22+
const isPastAction = _.some(actionQueue, (action) => action.name === name) || _.some(pastActions, name);
23+
if (isOneTime && isPastAction) {
24+
return Promise.reject(`Action (${name}) was already scheduled or performed once.`);
25+
}
26+
27+
return new Promise((resolve, reject) => {
28+
if (isImmediate) {
29+
setImmediate(() => resolve(name));
30+
return;
31+
}
32+
33+
actionQueue.push({
34+
name: name,
35+
resolve: resolve
36+
});
37+
});
38+
}
39+
40+
function idleHandler() {
41+
if (_.isEmpty(actionQueue)) {
42+
return;
43+
}
44+
45+
const action = actionQueue.shift();
46+
pastActions.push(action && action.name || "");
47+
action && action.resolve(action && action.name);
48+
}

0 commit comments

Comments
 (0)