@codingame/monaco-vscode-update-service-override 28.4.0 → 29.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (20) hide show
  1. package/package.json +2 -2
  2. package/vscode/src/vs/platform/update/common/update.config.contribution.js +39 -20
  3. package/vscode/src/vs/workbench/contrib/markdown/browser/markdownSettingRenderer.js +14 -14
  4. package/vscode/src/vs/workbench/contrib/update/browser/media/updateStatusBarEntry.css +0 -133
  5. package/vscode/src/vs/workbench/contrib/update/browser/media/updateTitleBarEntry.css +109 -0
  6. package/vscode/src/vs/workbench/contrib/update/browser/media/updateTooltip.css +159 -0
  7. package/vscode/src/vs/workbench/contrib/update/browser/releaseNotesEditor.d.ts +22 -1
  8. package/vscode/src/vs/workbench/contrib/update/browser/releaseNotesEditor.js +32 -14
  9. package/vscode/src/vs/workbench/contrib/update/browser/update.contribution.js +19 -17
  10. package/vscode/src/vs/workbench/contrib/update/browser/update.d.ts +5 -1
  11. package/vscode/src/vs/workbench/contrib/update/browser/update.js +132 -94
  12. package/vscode/src/vs/workbench/contrib/update/browser/updateStatusBarEntry.d.ts +9 -55
  13. package/vscode/src/vs/workbench/contrib/update/browser/updateStatusBarEntry.js +64 -395
  14. package/vscode/src/vs/workbench/contrib/update/browser/updateTitleBarEntry.d.ts +58 -0
  15. package/vscode/src/vs/workbench/contrib/update/browser/updateTitleBarEntry.js +319 -0
  16. package/vscode/src/vs/workbench/contrib/update/browser/updateTooltip.d.ts +66 -0
  17. package/vscode/src/vs/workbench/contrib/update/browser/updateTooltip.js +429 -0
  18. package/vscode/src/vs/workbench/contrib/update/common/updateUtils.d.ts +61 -0
  19. package/vscode/src/vs/workbench/contrib/update/common/updateUtils.js +141 -0
  20. package/vscode/src/vs/workbench/contrib/update/browser/media/releasenoteseditor.css +0 -9
@@ -0,0 +1,429 @@
1
+
2
+ import { registerCss } from '@codingame/monaco-vscode-api/css';
3
+ import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
4
+ import { $, append, addDisposableListener, clearNode, createTextNode } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/dom';
5
+ import { ActionBar } from '@codingame/monaco-vscode-api/vscode/vs/base/browser/ui/actionbar/actionbar';
6
+ import { toAction } from '@codingame/monaco-vscode-api/vscode/vs/base/common/actions';
7
+ import { CancellationToken } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
8
+ import { Codicon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/codicons';
9
+ import { MarkdownString } from '@codingame/monaco-vscode-api/vscode/vs/base/common/htmlContent';
10
+ import { Disposable, MutableDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
11
+ import { ThemeIcon } from '@codingame/monaco-vscode-api/vscode/vs/base/common/themables';
12
+ import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
13
+ import { IClipboardService } from '@codingame/monaco-vscode-api/vscode/vs/platform/clipboard/common/clipboardService.service';
14
+ import { ICommandService } from '@codingame/monaco-vscode-api/vscode/vs/platform/commands/common/commands.service';
15
+ import { IConfigurationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/configuration/common/configuration.service';
16
+ import { nativeHoverDelegate } from '@codingame/monaco-vscode-api/vscode/vs/platform/hover/browser/hover';
17
+ import { IHoverService } from '@codingame/monaco-vscode-api/vscode/vs/platform/hover/browser/hover.service';
18
+ import { openLinkFromMarkdown } from '@codingame/monaco-vscode-api/vscode/vs/platform/markdown/browser/markdownRenderer';
19
+ import { IMarkdownRendererService } from '@codingame/monaco-vscode-api/vscode/vs/platform/markdown/browser/markdownRenderer.service';
20
+ import { IMeteredConnectionService } from '@codingame/monaco-vscode-api/vscode/vs/platform/meteredConnection/common/meteredConnection.service';
21
+ import { IOpenerService } from '@codingame/monaco-vscode-api/vscode/vs/platform/opener/common/opener.service';
22
+ import { IProductService } from '@codingame/monaco-vscode-api/vscode/vs/platform/product/common/productService.service';
23
+ import { asTextOrError } from '@codingame/monaco-vscode-api/vscode/vs/platform/request/common/request';
24
+ import { IRequestService } from '@codingame/monaco-vscode-api/vscode/vs/platform/request/common/request.service';
25
+ import { StateType, DisablementReason } from '@codingame/monaco-vscode-api/vscode/vs/platform/update/common/update';
26
+ import { computeProgressPercent, formatBytes, computeDownloadSpeed, computeDownloadTimeRemaining, formatTimeRemaining, getUpdateInfoUrl, tryParseDate, formatDate } from '../common/updateUtils.js';
27
+ import * as updateTooltip from './media/updateTooltip.css';
28
+
29
+ registerCss(updateTooltip);
30
+ let UpdateTooltip = class UpdateTooltip extends Disposable {
31
+ constructor(
32
+ hostedByTitleBar,
33
+ clipboardService,
34
+ commandService,
35
+ configurationService,
36
+ hoverService,
37
+ markdownRendererService,
38
+ meteredConnectionService,
39
+ openerService,
40
+ productService,
41
+ requestService
42
+ ) {
43
+ super();
44
+ this.hostedByTitleBar = hostedByTitleBar;
45
+ this.clipboardService = clipboardService;
46
+ this.commandService = commandService;
47
+ this.configurationService = configurationService;
48
+ this.hoverService = hoverService;
49
+ this.markdownRendererService = markdownRendererService;
50
+ this.meteredConnectionService = meteredConnectionService;
51
+ this.openerService = openerService;
52
+ this.productService = productService;
53
+ this.requestService = requestService;
54
+ this.markdown = this._register(( new MutableDisposable()));
55
+ this.domNode = $(".update-tooltip");
56
+ const header = append(this.domNode, $(".header"));
57
+ this.titleNode = append(header, $(".title"));
58
+ const actionBar = this._register(( new ActionBar(header, {
59
+ hoverDelegate: nativeHoverDelegate
60
+ })));
61
+ actionBar.push(toAction({
62
+ id: "update.openSettings",
63
+ label: ( localize(14796, "Update Settings")),
64
+ class: ThemeIcon.asClassName(Codicon.gear),
65
+ run: () => this.runCommandAndClose("workbench.action.openSettings", "@id:update*")
66
+ }), {
67
+ icon: true,
68
+ label: false
69
+ });
70
+ this.productInfoNode = append(this.domNode, $(".product-info"));
71
+ const logoContainer = append(this.productInfoNode, $(".product-logo"));
72
+ logoContainer.setAttribute("role", "img");
73
+ logoContainer.setAttribute("aria-label", this.productService.nameLong);
74
+ const details = append(this.productInfoNode, $(".product-details"));
75
+ this.productNameNode = append(details, $(".product-name"));
76
+ this.productNameNode.textContent = this.productService.nameLong;
77
+ const currentVersionRow = this.createVersionRow(details);
78
+ this.currentVersionNode = currentVersionRow.label;
79
+ this.currentVersionCopyValue = currentVersionRow.copyValue;
80
+ const latestVersionRow = this.createVersionRow(details);
81
+ this.latestVersionNode = latestVersionRow.label;
82
+ this.latestVersionCopyValue = latestVersionRow.copyValue;
83
+ this.releaseDateNode = append(details, $(".product-release-date"));
84
+ this.releaseNotesLink = append(details, $("a.release-notes-link"));
85
+ this.releaseNotesLink.textContent = ( localize(14797, "Release Notes"));
86
+ this.releaseNotesLink.href = "#";
87
+ this._register(addDisposableListener(this.releaseNotesLink, "click", e => {
88
+ e.preventDefault();
89
+ if (this.releaseNotesVersion) {
90
+ this.runCommandAndClose("update.showCurrentReleaseNotes", this.releaseNotesVersion);
91
+ }
92
+ }));
93
+ this.progressContainer = append(this.domNode, $(".progress-container"));
94
+ const progressBar = append(this.progressContainer, $(".progress-bar"));
95
+ this.progressFill = append(progressBar, $(".progress-fill"));
96
+ const progressText = append(this.progressContainer, $(".progress-text"));
97
+ this.progressPercentNode = append(progressText, $("span"));
98
+ this.progressSizeNode = append(progressText, $("span"));
99
+ this.downloadStatsContainer = append(this.progressContainer, $(".download-stats"));
100
+ this.timeRemainingNode = append(this.downloadStatsContainer, $(".time-remaining"));
101
+ this.speedInfoNode = append(this.downloadStatsContainer, $(".speed-info"));
102
+ this.markdownContainer = append(this.domNode, $(".update-markdown"));
103
+ this.messageNode = append(this.domNode, $(".state-message"));
104
+ this.updateCurrentVersion();
105
+ }
106
+ updateCurrentVersion() {
107
+ const productVersion = this.productService.version;
108
+ if (productVersion) {
109
+ const currentCommitId = this.productService.commit?.substring(0, 7);
110
+ this.currentVersionNode.textContent = currentCommitId ? ( localize(14798, "Current Version: {0} ({1})", productVersion, currentCommitId)) : ( localize(14799, "Current Version: {0}", productVersion));
111
+ this.currentVersionCopyValue.value = currentCommitId ? `${productVersion} (${this.productService.commit})` : productVersion;
112
+ this.currentVersionNode.parentElement.style.display = "";
113
+ } else {
114
+ this.currentVersionNode.parentElement.style.display = "none";
115
+ }
116
+ }
117
+ hideAll() {
118
+ this.productInfoNode.style.display = "";
119
+ this.progressContainer.style.display = "none";
120
+ this.speedInfoNode.textContent = "";
121
+ this.timeRemainingNode.textContent = "";
122
+ this.messageNode.style.display = "none";
123
+ this.markdownContainer.style.display = "none";
124
+ this.markdown.clear();
125
+ }
126
+ renderState(state) {
127
+ this.hideAll();
128
+ switch (state.type) {
129
+ case StateType.Uninitialized:
130
+ this.renderUninitialized();
131
+ break;
132
+ case StateType.Disabled:
133
+ this.renderDisabled(state);
134
+ break;
135
+ case StateType.Idle:
136
+ this.renderIdle(state);
137
+ break;
138
+ case StateType.CheckingForUpdates:
139
+ this.renderCheckingForUpdates();
140
+ break;
141
+ case StateType.AvailableForDownload:
142
+ this.renderAvailableForDownload(state);
143
+ break;
144
+ case StateType.Downloading:
145
+ this.renderDownloading(state);
146
+ break;
147
+ case StateType.Downloaded:
148
+ this.renderDownloaded(state);
149
+ break;
150
+ case StateType.Updating:
151
+ this.renderUpdating(state);
152
+ break;
153
+ case StateType.Ready:
154
+ this.renderReady(state);
155
+ break;
156
+ case StateType.Overwriting:
157
+ this.renderOverwriting(state);
158
+ break;
159
+ }
160
+ }
161
+ renderUninitialized() {
162
+ this.renderTitleAndInfo(( localize(14800, "Initializing")));
163
+ this.renderMessage(( localize(14801, "Initializing update service...")));
164
+ }
165
+ renderDisabled(
166
+ {
167
+ reason
168
+ }
169
+ ) {
170
+ this.renderTitleAndInfo(( localize(14802, "Updates Disabled")));
171
+ switch (reason) {
172
+ case DisablementReason.NotBuilt:
173
+ this.renderMessage(( localize(14803, "Updates are not available for this build.")), Codicon.info);
174
+ break;
175
+ case DisablementReason.DisabledByEnvironment:
176
+ this.renderMessage(( localize(14804, "Updates are disabled by the --disable-updates command line flag.")), Codicon.warning);
177
+ break;
178
+ case DisablementReason.ManuallyDisabled:
179
+ this.renderMessage(( localize(
180
+ 14805,
181
+ "Updates are manually disabled. Change the \"update.mode\" setting to enable."
182
+ )), Codicon.warning);
183
+ break;
184
+ case DisablementReason.Policy:
185
+ this.renderMessage(( localize(14806, "Updates are disabled by organization policy.")), Codicon.info);
186
+ break;
187
+ case DisablementReason.MissingConfiguration:
188
+ this.renderMessage(( localize(14807, "Updates are disabled because no update URL is configured.")), Codicon.info);
189
+ break;
190
+ case DisablementReason.InvalidConfiguration:
191
+ this.renderMessage(( localize(14808, "Updates are disabled because the update URL is invalid.")), Codicon.error);
192
+ break;
193
+ case DisablementReason.RunningAsAdmin:
194
+ this.renderMessage(( localize(
195
+ 14809,
196
+ "Updates are not available when running a user install of {0} as administrator.",
197
+ this.productService.nameShort
198
+ )), Codicon.warning);
199
+ break;
200
+ default:
201
+ this.renderMessage(( localize(14810, "Updates are disabled.")), Codicon.warning);
202
+ break;
203
+ }
204
+ }
205
+ renderIdle(
206
+ {
207
+ error,
208
+ notAvailable
209
+ }
210
+ ) {
211
+ if (error) {
212
+ this.renderTitleAndInfo(( localize(14811, "Update Error")));
213
+ this.renderMessage(error, Codicon.error);
214
+ return;
215
+ }
216
+ if (notAvailable) {
217
+ this.renderTitleAndInfo(( localize(14812, "No Update Available")));
218
+ this.renderMessage(( localize(14813, "There are no updates currently available.")), Codicon.info);
219
+ return;
220
+ }
221
+ this.renderTitleAndInfo(( localize(14814, "Up to Date")));
222
+ switch (this.configurationService.getValue("update.mode")) {
223
+ case "none":
224
+ this.renderMessage(( localize(14815, "Automatic updates are disabled.")), Codicon.warning);
225
+ break;
226
+ case "manual":
227
+ this.renderMessage(( localize(
228
+ 14816,
229
+ "Automatic updates will be checked but not installed automatically."
230
+ )));
231
+ break;
232
+ case "start":
233
+ this.renderMessage(( localize(14817, "Updates will be applied on restart.")));
234
+ break;
235
+ case "default":
236
+ if (this.meteredConnectionService.isConnectionMetered) {
237
+ this.renderMessage(( localize(
238
+ 14818,
239
+ "Automatic updates are paused because the network connection is metered."
240
+ )), Codicon.radioTower);
241
+ } else {
242
+ this.renderMessage(( localize(14819, "Automatic updates are enabled. Happy Coding!")), Codicon.smiley);
243
+ }
244
+ break;
245
+ }
246
+ }
247
+ renderCheckingForUpdates() {
248
+ this.renderTitleAndInfo(( localize(14820, "Checking for Updates")));
249
+ this.renderMessage(( localize(14821, "Checking for updates, please wait...")));
250
+ }
251
+ renderAvailableForDownload(
252
+ {
253
+ update
254
+ }
255
+ ) {
256
+ this.renderTitleAndInfo(( localize(14822, "Update Available")), update);
257
+ if (this.hostedByTitleBar) {
258
+ this.renderMessage(( localize(14823, "Click the Update button to download.")));
259
+ }
260
+ }
261
+ renderDownloading(state) {
262
+ this.renderTitleAndInfo(( localize(14824, "Downloading Update")), state.update);
263
+ const {
264
+ downloadedBytes,
265
+ totalBytes
266
+ } = state;
267
+ if (downloadedBytes !== undefined && totalBytes !== undefined && totalBytes > 0) {
268
+ const percentage = computeProgressPercent(downloadedBytes, totalBytes) ?? 0;
269
+ this.progressFill.style.width = `${percentage}%`;
270
+ this.progressPercentNode.textContent = `${percentage}%`;
271
+ this.progressSizeNode.textContent = `${formatBytes(downloadedBytes)} / ${formatBytes(totalBytes)}`;
272
+ this.progressContainer.style.display = "";
273
+ const speed = computeDownloadSpeed(state);
274
+ if (speed !== undefined && speed > 0) {
275
+ this.speedInfoNode.textContent = ( localize(14825, "{0}/s", formatBytes(speed)));
276
+ }
277
+ const timeRemaining = computeDownloadTimeRemaining(state);
278
+ if (timeRemaining !== undefined && timeRemaining > 0) {
279
+ this.timeRemainingNode.textContent = `~${formatTimeRemaining(timeRemaining)} ${( localize(14826, "remaining"))}`;
280
+ }
281
+ this.downloadStatsContainer.style.display = "";
282
+ } else {
283
+ this.renderMessage(( localize(14827, "Downloading update, please wait...")));
284
+ }
285
+ }
286
+ renderDownloaded(
287
+ {
288
+ update
289
+ }
290
+ ) {
291
+ this.renderTitleAndInfo(( localize(14828, "Update is Ready to Install")), update);
292
+ if (this.hostedByTitleBar) {
293
+ this.renderMessage(( localize(14829, "Click the Update button to install.")));
294
+ }
295
+ }
296
+ renderUpdating(
297
+ {
298
+ update,
299
+ currentProgress,
300
+ maxProgress
301
+ }
302
+ ) {
303
+ this.renderTitleAndInfo(( localize(14830, "Installing Update")), update);
304
+ const percentage = computeProgressPercent(currentProgress, maxProgress);
305
+ if (percentage !== undefined) {
306
+ this.progressFill.style.width = `${percentage}%`;
307
+ this.progressPercentNode.textContent = `${percentage}%`;
308
+ this.progressSizeNode.textContent = "";
309
+ this.progressContainer.style.display = "";
310
+ } else {
311
+ this.renderMessage(( localize(14831, "Installing update, please wait...")));
312
+ }
313
+ }
314
+ renderReady(
315
+ {
316
+ update
317
+ }
318
+ ) {
319
+ this.renderTitleAndInfo(( localize(14832, "Update Installed")), update);
320
+ if (this.hostedByTitleBar) {
321
+ this.renderMessage(( localize(14833, "Click the Update button to restart and apply.")));
322
+ }
323
+ }
324
+ renderOverwriting(
325
+ {
326
+ update
327
+ }
328
+ ) {
329
+ this.renderTitleAndInfo(( localize(14834, "Downloading Newer Update")), update);
330
+ this.renderMessage(( localize(14835, "A newer update was released. Downloading, please wait...")));
331
+ }
332
+ async renderPostInstall() {
333
+ this.hideAll();
334
+ this.renderTitleAndInfo(( localize(14836, "New Update Installed")));
335
+ this.renderMessage(( localize(14837, "See release notes for details on what's new in this release.")), Codicon.info);
336
+ let text = null;
337
+ try {
338
+ const url = getUpdateInfoUrl(this.productService.version);
339
+ const context = await this.requestService.request({
340
+ url,
341
+ callSite: "updateTooltip"
342
+ }, CancellationToken.None);
343
+ text = await asTextOrError(context);
344
+ } catch {}
345
+ if (!text) {
346
+ return;
347
+ }
348
+ this.titleNode.textContent = ( localize(14838, "New in {0}", this.productService.version));
349
+ this.productInfoNode.style.display = "none";
350
+ this.messageNode.style.display = "none";
351
+ const rendered = this.markdownRendererService.render(( new MarkdownString(text, {
352
+ isTrusted: true,
353
+ supportHtml: true,
354
+ supportThemeIcons: true
355
+ })), {
356
+ actionHandler: (link, mdStr) => {
357
+ openLinkFromMarkdown(this.openerService, link, mdStr.isTrusted);
358
+ this.hoverService.hideHover(true);
359
+ }
360
+ });
361
+ this.markdown.value = rendered;
362
+ clearNode(this.markdownContainer);
363
+ this.markdownContainer.appendChild(rendered.element);
364
+ this.markdownContainer.style.display = "";
365
+ }
366
+ renderTitleAndInfo(title, update) {
367
+ this.titleNode.textContent = title;
368
+ const version = update?.productVersion;
369
+ if (version) {
370
+ const updateCommitId = update.version?.substring(0, 7);
371
+ this.latestVersionNode.textContent = updateCommitId ? ( localize(14839, "Latest Version: {0} ({1})", version, updateCommitId)) : ( localize(14840, "Latest Version: {0}", version));
372
+ this.latestVersionCopyValue.value = updateCommitId ? `${version} (${update.version})` : version;
373
+ this.latestVersionNode.parentElement.style.display = "";
374
+ } else {
375
+ this.latestVersionNode.parentElement.style.display = "none";
376
+ }
377
+ const releaseDate = update?.timestamp ?? tryParseDate(this.productService.date);
378
+ if (typeof releaseDate === "number" && releaseDate > 0) {
379
+ this.releaseDateNode.textContent = ( localize(14841, "Released {0}", formatDate(releaseDate)));
380
+ this.releaseDateNode.style.display = "";
381
+ } else {
382
+ this.releaseDateNode.style.display = "none";
383
+ }
384
+ this.releaseNotesVersion = version ?? this.productService.version;
385
+ this.releaseNotesLink.style.display = this.releaseNotesVersion ? "" : "none";
386
+ }
387
+ renderMessage(message, icon) {
388
+ clearNode(this.messageNode);
389
+ if (icon) {
390
+ const iconNode = append(this.messageNode, $(".state-message-icon"));
391
+ iconNode.classList.add(...ThemeIcon.asClassNameArray(icon));
392
+ }
393
+ append(this.messageNode, createTextNode(message));
394
+ this.messageNode.style.display = "";
395
+ }
396
+ createVersionRow(parent) {
397
+ const row = append(parent, $(".product-version"));
398
+ const label = append(row, $("span"));
399
+ const copyValue = {
400
+ value: ""
401
+ };
402
+ const copyButton = append(row, $("a.copy-version-button"));
403
+ copyButton.setAttribute("role", "button");
404
+ copyButton.setAttribute("tabindex", "0");
405
+ const title = ( localize(14842, "Copy"));
406
+ copyButton.title = title;
407
+ copyButton.setAttribute("aria-label", title);
408
+ const copyIcon = append(copyButton, $(".copy-icon"));
409
+ copyIcon.classList.add(...ThemeIcon.asClassNameArray(Codicon.copy));
410
+ this._register(addDisposableListener(copyButton, "click", e => {
411
+ e.preventDefault();
412
+ e.stopPropagation();
413
+ if (copyValue.value) {
414
+ this.clipboardService.writeText(copyValue.value);
415
+ }
416
+ }));
417
+ return {
418
+ label,
419
+ copyValue
420
+ };
421
+ }
422
+ runCommandAndClose(command, ...args) {
423
+ this.commandService.executeCommand(command, ...args);
424
+ this.hoverService.hideHover(true);
425
+ }
426
+ };
427
+ UpdateTooltip = ( __decorate([( __param(1, IClipboardService)), ( __param(2, ICommandService)), ( __param(3, IConfigurationService)), ( __param(4, IHoverService)), ( __param(5, IMarkdownRendererService)), ( __param(6, IMeteredConnectionService)), ( __param(7, IOpenerService)), ( __param(8, IProductService)), ( __param(9, IRequestService))], UpdateTooltip));
428
+
429
+ export { UpdateTooltip };
@@ -0,0 +1,61 @@
1
+ import { Downloading } from "@codingame/monaco-vscode-api/vscode/vs/platform/update/common/update";
2
+ /**
3
+ * Returns the progress percentage based on the current and maximum progress values.
4
+ */
5
+ export declare function computeProgressPercent(current: number | undefined, max: number | undefined): number | undefined;
6
+ /**
7
+ * Computes an estimate of remaining download time in seconds.
8
+ */
9
+ export declare function computeDownloadTimeRemaining(state: Downloading): number | undefined;
10
+ /**
11
+ * Computes the current download speed in bytes per second.
12
+ */
13
+ export declare function computeDownloadSpeed(state: Downloading): number | undefined;
14
+ /**
15
+ * Computes the version to use for fetching update info.
16
+ * - If the minor version differs: returns `{major}.{minor}` (e.g., 1.108.2 -> 1.109.5 => 1.109)
17
+ * - If the same minor: returns the target version as-is (e.g., 1.109.2 -> 1.109.5 => 1.109.5)
18
+ */
19
+ export declare function computeUpdateInfoVersion(currentVersion: string, targetVersion: string): string | undefined;
20
+ /**
21
+ * Computes the URL to fetch update info from.
22
+ * Follows the release notes URL pattern but with `_update` suffix.
23
+ */
24
+ export declare function getUpdateInfoUrl(version: string): string;
25
+ /**
26
+ * Formats the time remaining as a human-readable string.
27
+ */
28
+ export declare function formatTimeRemaining(seconds: number): string;
29
+ /**
30
+ * Formats a byte count as a human-readable string.
31
+ */
32
+ export declare function formatBytes(bytes: number): string;
33
+ /**
34
+ * Tries to parse a date string and returns the timestamp or undefined if parsing fails.
35
+ */
36
+ export declare function tryParseDate(date: string | undefined): number | undefined;
37
+ /**
38
+ * Formats a timestamp as a localized date string.
39
+ */
40
+ export declare function formatDate(timestamp: number): string;
41
+ /**
42
+ * Formats a number to 1 decimal place, omitting ".0" for whole numbers.
43
+ */
44
+ export declare function formatDecimal(value: number): string;
45
+ export interface IVersion {
46
+ major: number;
47
+ minor: number;
48
+ patch: number;
49
+ }
50
+ /**
51
+ * Parses a version string in the format "major.minor.patch" and returns an object with the components.
52
+ */
53
+ export declare function tryParseVersion(version: string | undefined): IVersion | undefined;
54
+ /**
55
+ * Processes an error message and returns a user-friendly version of it, or undefined if the error should be ignored.
56
+ */
57
+ export declare function preprocessError(error?: string): string | undefined;
58
+ /**
59
+ * Determines whether there is a major or minor version change between two versions.
60
+ */
61
+ export declare function isMajorMinorVersionChange(previousVersion?: string, newVersion?: string): boolean;
@@ -0,0 +1,141 @@
1
+
2
+ import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
3
+
4
+ function computeProgressPercent(current, max) {
5
+ if (current === undefined || max === undefined || max <= 0) {
6
+ return undefined;
7
+ }
8
+ return Math.max(Math.min(Math.round((current / max) * 100), 100), 0);
9
+ }
10
+ function computeDownloadTimeRemaining(state) {
11
+ const {
12
+ downloadedBytes,
13
+ totalBytes,
14
+ startTime
15
+ } = state;
16
+ if (downloadedBytes === undefined || totalBytes === undefined || startTime === undefined) {
17
+ return undefined;
18
+ }
19
+ const elapsedMs = Date.now() - startTime;
20
+ if (downloadedBytes <= 0 || totalBytes <= 0 || elapsedMs <= 0) {
21
+ return undefined;
22
+ }
23
+ const remainingBytes = totalBytes - downloadedBytes;
24
+ if (remainingBytes <= 0) {
25
+ return 0;
26
+ }
27
+ const bytesPerMs = downloadedBytes / elapsedMs;
28
+ if (bytesPerMs <= 0) {
29
+ return undefined;
30
+ }
31
+ const remainingMs = remainingBytes / bytesPerMs;
32
+ return Math.ceil(remainingMs / 1000);
33
+ }
34
+ function computeDownloadSpeed(state) {
35
+ const {
36
+ downloadedBytes,
37
+ startTime
38
+ } = state;
39
+ if (downloadedBytes === undefined || startTime === undefined) {
40
+ return undefined;
41
+ }
42
+ const elapsedMs = Date.now() - startTime;
43
+ if (elapsedMs <= 0 || downloadedBytes <= 0) {
44
+ return undefined;
45
+ }
46
+ return (downloadedBytes / elapsedMs) * 1000;
47
+ }
48
+ function getUpdateInfoUrl(version) {
49
+ const versionLabel = version.replace(/\./g, "_").replace(/_0$/, "");
50
+ return `https://code.visualstudio.com/raw/v${versionLabel}_update.md`;
51
+ }
52
+ function formatTimeRemaining(seconds) {
53
+ const hours = seconds / 3600;
54
+ if (hours >= 1) {
55
+ const formattedHours = formatDecimal(hours);
56
+ if (formattedHours === "1") {
57
+ return localize(14843, "{0} hour", formattedHours);
58
+ } else {
59
+ return localize(14844, "{0} hours", formattedHours);
60
+ }
61
+ }
62
+ const minutes = Math.floor(seconds / 60);
63
+ if (minutes >= 1) {
64
+ return localize(14845, "{0} min", minutes);
65
+ }
66
+ return localize(14846, "{0}s", seconds);
67
+ }
68
+ function formatBytes(bytes) {
69
+ if (bytes < 1024) {
70
+ return localize(14847, "{0} B", bytes);
71
+ }
72
+ const kb = bytes / 1024;
73
+ if (kb < 1024) {
74
+ return localize(14848, "{0} KB", formatDecimal(kb));
75
+ }
76
+ const mb = kb / 1024;
77
+ if (mb < 1024) {
78
+ return localize(14849, "{0} MB", formatDecimal(mb));
79
+ }
80
+ const gb = mb / 1024;
81
+ return localize(14850, "{0} GB", formatDecimal(gb));
82
+ }
83
+ function tryParseDate(date) {
84
+ if (date === undefined) {
85
+ return undefined;
86
+ }
87
+ try {
88
+ const parsed = Date.parse(date);
89
+ return isNaN(parsed) ? undefined : parsed;
90
+ } catch {
91
+ return undefined;
92
+ }
93
+ }
94
+ function formatDate(timestamp) {
95
+ return ( new Date(timestamp)).toLocaleDateString(undefined, {
96
+ year: "numeric",
97
+ month: "short",
98
+ day: "numeric"
99
+ });
100
+ }
101
+ function formatDecimal(value) {
102
+ const rounded = Math.round(value * 10) / 10;
103
+ return rounded % 1 === 0 ? ( rounded.toString()) : rounded.toFixed(1);
104
+ }
105
+ function tryParseVersion(version) {
106
+ if (version === undefined) {
107
+ return undefined;
108
+ }
109
+ const match = /^(\d{1,10})\.(\d{1,10})\.(\d{1,10})/.exec(version);
110
+ if (!match) {
111
+ return undefined;
112
+ }
113
+ try {
114
+ return {
115
+ major: parseInt(match[1]),
116
+ minor: parseInt(match[2]),
117
+ patch: parseInt(match[3])
118
+ };
119
+ } catch {
120
+ return undefined;
121
+ }
122
+ }
123
+ function preprocessError(error) {
124
+ if (!error) {
125
+ return undefined;
126
+ }
127
+ if (/The request timed out|The network connection was lost/i.test(error)) {
128
+ return undefined;
129
+ }
130
+ return error.replace(
131
+ /See https:\/\/github\.com\/Squirrel\/Squirrel\.Mac\/issues\/182 for more information/,
132
+ "This might mean the application was put on quarantine by macOS. See [this link](https://github.com/microsoft/vscode/issues/7426#issuecomment-425093469) for more information"
133
+ );
134
+ }
135
+ function isMajorMinorVersionChange(previousVersion, newVersion) {
136
+ const previous = tryParseVersion(previousVersion);
137
+ const current = tryParseVersion(newVersion);
138
+ return !!previous && !!current && (previous.major !== current.major || previous.minor !== current.minor);
139
+ }
140
+
141
+ export { computeDownloadSpeed, computeDownloadTimeRemaining, computeProgressPercent, formatBytes, formatDate, formatDecimal, formatTimeRemaining, getUpdateInfoUrl, isMajorMinorVersionChange, preprocessError, tryParseDate, tryParseVersion };
@@ -1,9 +0,0 @@
1
- /*---------------------------------------------------------------------------------------------
2
- * Copyright (c) Microsoft Corporation. All rights reserved.
3
- * Licensed under the MIT License. See License.txt in the project root for license information.
4
- *--------------------------------------------------------------------------------------------*/
5
-
6
- .file-icons-enabled .show-file-icons .webview-vs_code_release_notes-name-file-icon.file-icon::before {
7
- content: ' ';
8
- background-image: var(--product-icon, url('../../../../browser/media/code-icon.svg'));
9
- }