-
Notifications
You must be signed in to change notification settings - Fork 101
Expand file tree
/
Copy pathnotificationManager.ts
More file actions
118 lines (99 loc) · 4.6 KB
/
Copy pathnotificationManager.ts
File metadata and controls
118 lines (99 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
import { commands, ExtensionContext, window } from "vscode";
import { UpgradeReason, type IUpgradeIssuesRenderer, type UpgradeIssue } from "../type";
import { buildCVENotificationMessage, buildFixPrompt, buildNotificationMessage, getExtensionState, type ExtensionState } from "../utility";
import { Commands } from "../../commands";
import { Settings } from "../../settings";
import { instrumentOperation, sendInfo } from "vscode-extension-telemetry-wrapper";
import { ExtensionName, Upgrade } from "../../constants";
import { CveUpgradeIssue } from "../cve";
const KEY_PREFIX = 'javaupgrade.notificationManager';
const NEXT_SHOW_TS_KEY = `${KEY_PREFIX}.nextShowTs`;
const BUTTON_TEXT_NOT_NOW = "Not Now";
// Action button label keyed by the install state of the app modernization extension.
const UPGRADE_BUTTON_TEXT: Record<ExtensionState, string> = {
"up-to-date": "Upgrade Now",
"outdated": "Update Extension and Upgrade",
"not-installed": "Install Extension and Upgrade",
};
const FIX_CVE_BUTTON_TEXT: Record<ExtensionState, string> = {
"up-to-date": "Fix Now",
"outdated": "Update Extension and Fix",
"not-installed": "Install Extension and Fix",
};
const SECONDS_IN_A_DAY = 24 * 60 * 60;
const SECONDS_COUNT_BEFORE_NOTIFICATION_RESHOW = 10 * SECONDS_IN_A_DAY;
function getNowTs() {
return Number(new Date()) / 1000;
}
class NotificationManager implements IUpgradeIssuesRenderer {
private hasShown = false;
private context?: ExtensionContext;
initialize(context: ExtensionContext) {
this.context = context;
}
async render(issues: UpgradeIssue[]) {
return (instrumentOperation(
"java.dependency.showUpgradeNotification",
async (operationId: string) => {
if (issues.length === 0) {
return;
}
if (!this.shouldShow() || this.hasShown) {
return;
}
this.hasShown = true;
// Prefer Java upgrade recommendations over CVE fixes: only fall back
// to a CVE notification when there is no upgrade issue to recommend.
const cveIssues = issues.filter(
(i): i is CveUpgradeIssue => i.reason === UpgradeReason.CVE
);
const upgradeIssues = issues.filter(
(i) => i.reason !== UpgradeReason.CVE
);
const isCVE = upgradeIssues.length === 0;
const issue = isCVE ? cveIssues[0] : upgradeIssues[0];
const extensionState = getExtensionState(ExtensionName.APP_MODERNIZATION_UPGRADE_FOR_JAVA);
const source = isCVE ? Upgrade.SOURCE_CVE : Upgrade.SOURCE_JAVA_UPGRADE;
const notificationMessage = isCVE
? buildCVENotificationMessage(cveIssues, extensionState)
: buildNotificationMessage(issue, extensionState);
const actionButtonText = isCVE
? FIX_CVE_BUTTON_TEXT[extensionState]
: UPGRADE_BUTTON_TEXT[extensionState];
sendInfo(operationId, {
operationName: "java.dependency.upgradeNotification.show",
extensionState,
source,
});
const selection = await window.showInformationMessage(
notificationMessage,
actionButtonText,
BUTTON_TEXT_NOT_NOW
);
sendInfo(operationId, {
operationName: "java.dependency.upgradeNotification.runUpgrade",
choice: selection ?? "",
});
if (selection === actionButtonText) {
commands.executeCommand(Commands.JAVA_UPGRADE_WITH_COPILOT, buildFixPrompt(issue), source);
} else if (selection === BUTTON_TEXT_NOT_NOW) {
this.setNextShowTs(getNowTs() + SECONDS_COUNT_BEFORE_NOTIFICATION_RESHOW);
}
}
))();
}
private shouldShow() {
return Settings.getEnableDependencyCheckup()
&& ((this.getNextShowTs() ?? 0) <= getNowTs());
}
private getNextShowTs() {
return this.context?.globalState.get<number>(NEXT_SHOW_TS_KEY);
}
private setNextShowTs(num: number) {
return this.context?.globalState.update(NEXT_SHOW_TS_KEY, num);
}
}
const notificationManager = new NotificationManager();
export default notificationManager;