mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-04 08:58:41 -05:00
update animation and background color
This commit is contained in:
@@ -645,6 +645,8 @@
|
||||
"--vscode-searchEditor-findMatchBorder",
|
||||
"--vscode-searchEditor-textInputBorder",
|
||||
"--vscode-selection-background",
|
||||
"--vscode-sessionsUpdateButton-downloadedBackground",
|
||||
"--vscode-sessionsUpdateButton-downloadingBackground",
|
||||
"--vscode-settings-checkboxBackground",
|
||||
"--vscode-settings-checkboxBorder",
|
||||
"--vscode-settings-checkboxForeground",
|
||||
|
||||
@@ -7,6 +7,7 @@ import { localize } from '../../nls.js';
|
||||
import { registerColor, transparent } from '../../platform/theme/common/colorUtils.js';
|
||||
import { contrastBorder, iconForeground } from '../../platform/theme/common/colorRegistry.js';
|
||||
import { Color } from '../../base/common/color.js';
|
||||
import { buttonBackground } from '../../platform/theme/common/colors/inputColors.js';
|
||||
import { SIDE_BAR_BACKGROUND, SIDE_BAR_FOREGROUND } from '../../workbench/common/theme.js';
|
||||
|
||||
// Sessions sidebar background color
|
||||
@@ -55,3 +56,16 @@ export const agentFeedbackInputWidgetBorder = registerColor(
|
||||
{ dark: transparent(iconForeground, 0.8), light: transparent(iconForeground, 0.8), hcDark: contrastBorder, hcLight: contrastBorder },
|
||||
localize('agentFeedbackInputWidget.border', 'Border color of the agent feedback input widget shown in the editor.')
|
||||
);
|
||||
|
||||
// Sessions update button colors
|
||||
export const sessionsUpdateButtonDownloadingBackground = registerColor(
|
||||
'sessionsUpdateButton.downloadingBackground',
|
||||
transparent(buttonBackground, 0.4),
|
||||
localize('sessionsUpdateButton.downloadingBackground', 'Background color of the update button to show download progress in the agent sessions window.')
|
||||
);
|
||||
|
||||
export const sessionsUpdateButtonDownloadedBackground = registerColor(
|
||||
'sessionsUpdateButton.downloadedBackground',
|
||||
transparent(buttonBackground, 0.7),
|
||||
localize('sessionsUpdateButton.downloadedBackground', 'Background color of the update button when download is complete in the agent sessions window.')
|
||||
);
|
||||
|
||||
@@ -23,7 +23,9 @@ import { IAction } from '../../../../base/common/actions.js';
|
||||
import { Button } from '../../../../base/browser/ui/button/button.js';
|
||||
import { defaultButtonStyles } from '../../../../platform/theme/browser/defaultStyles.js';
|
||||
import { Codicon } from '../../../../base/common/codicons.js';
|
||||
import { IUpdateService, StateType } from '../../../../platform/update/common/update.js';
|
||||
import { Downloading, IUpdateService, State, StateType } from '../../../../platform/update/common/update.js';
|
||||
import { asCssVariable } from '../../../../platform/theme/common/colorUtils.js';
|
||||
import { sessionsUpdateButtonDownloadingBackground, sessionsUpdateButtonDownloadedBackground } from '../../../common/theme.js';
|
||||
|
||||
// --- Account Menu Items --- //
|
||||
const AccountMenu = new MenuId('SessionsAccountMenu');
|
||||
@@ -160,7 +162,7 @@ class AccountWidget extends ActionViewItem {
|
||||
}
|
||||
}
|
||||
|
||||
class UpdateWidget extends ActionViewItem {
|
||||
export class UpdateWidget extends ActionViewItem {
|
||||
|
||||
private updateButton: Button | undefined;
|
||||
private readonly viewItemDisposables = this._register(new DisposableStore());
|
||||
@@ -222,9 +224,44 @@ class UpdateWidget extends ActionViewItem {
|
||||
if (this.isUpdatePending() && !this.isUpdateReady()) {
|
||||
this.updateButton.enabled = false;
|
||||
this.updateButton.label = `$(${Codicon.loading.id}~spin) ${this.getUpdateProgressMessage(state.type)}`;
|
||||
this.updateDownloadProgress(state);
|
||||
} else {
|
||||
this.updateButton.enabled = true;
|
||||
this.updateButton.label = `$(${Codicon.debugRestart.id}) ${localize('update', "Update")}`;
|
||||
const color = asCssVariable(sessionsUpdateButtonDownloadedBackground);
|
||||
this.updateButton.element.style.backgroundImage = `linear-gradient(to right, ${color} 100%, transparent 100%)`;
|
||||
}
|
||||
}
|
||||
|
||||
private updateDownloadProgress(state: State): void {
|
||||
if (!this.updateButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
const el = this.updateButton.element;
|
||||
|
||||
if (state.type === StateType.Downloading) {
|
||||
const { downloadedBytes, totalBytes } = state as Downloading;
|
||||
if (downloadedBytes !== undefined && totalBytes && totalBytes > 0) {
|
||||
const percent = Math.min(100, Math.round((downloadedBytes / totalBytes) * 100));
|
||||
const color = asCssVariable(sessionsUpdateButtonDownloadingBackground);
|
||||
el.style.backgroundImage = `linear-gradient(to right, ${color} ${percent}%, transparent ${percent}%)`;
|
||||
} else {
|
||||
// Indeterminate: show a subtle pulsing background
|
||||
const color = asCssVariable(sessionsUpdateButtonDownloadingBackground);
|
||||
el.style.backgroundImage = `linear-gradient(to right, ${color} 0%, transparent 100%)`;
|
||||
}
|
||||
} else if (state.type === StateType.Downloaded) {
|
||||
const color = asCssVariable(sessionsUpdateButtonDownloadedBackground);
|
||||
el.style.backgroundImage = `linear-gradient(to right, ${color} 100%, transparent 100%)`;
|
||||
} else {
|
||||
this.clearDownloadProgress();
|
||||
}
|
||||
}
|
||||
|
||||
private clearDownloadProgress(): void {
|
||||
if (this.updateButton) {
|
||||
this.updateButton.element.style.backgroundImage = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Action } from '../../../../../base/common/actions.js';
|
||||
import { Emitter } from '../../../../../base/common/event.js';
|
||||
import { IUpdateService, State } from '../../../../../platform/update/common/update.js';
|
||||
import { ComponentFixtureContext, createEditorServices, defineComponentFixture, defineThemedFixtureGroup } from '../../../../../workbench/test/browser/componentFixtures/fixtureUtils.js';
|
||||
import { UpdateWidget } from '../../browser/account.contribution.js';
|
||||
|
||||
// Ensure color registrations are loaded
|
||||
import '../../../../common/theme.js';
|
||||
import '../../../../../platform/theme/common/colors/inputColors.js';
|
||||
|
||||
// Import the CSS
|
||||
import '../../../../browser/media/sidebarActionButton.css';
|
||||
import '../../browser/media/accountWidget.css';
|
||||
|
||||
const mockUpdate = { version: '1.0.0' };
|
||||
|
||||
function createMockUpdateService(state: State): IUpdateService {
|
||||
const onStateChange = new Emitter<State>();
|
||||
const service: IUpdateService = {
|
||||
_serviceBrand: undefined,
|
||||
state,
|
||||
onStateChange: onStateChange.event,
|
||||
checkForUpdates: async () => { },
|
||||
downloadUpdate: async () => { },
|
||||
applyUpdate: async () => { },
|
||||
quitAndInstall: async () => { },
|
||||
isLatestVersion: async () => true,
|
||||
_applySpecificUpdate: async () => { },
|
||||
setInternalOrg: async () => { },
|
||||
};
|
||||
return service;
|
||||
}
|
||||
|
||||
function renderUpdateWidget(ctx: ComponentFixtureContext, state: State): void {
|
||||
ctx.container.style.padding = '16px';
|
||||
ctx.container.style.width = '300px';
|
||||
ctx.container.style.backgroundColor = 'var(--vscode-sideBar-background)';
|
||||
|
||||
const mockService = createMockUpdateService(state);
|
||||
|
||||
const instantiationService = createEditorServices(ctx.disposableStore, {
|
||||
colorTheme: ctx.theme,
|
||||
additionalServices: (reg) => {
|
||||
reg.defineInstance(IUpdateService, mockService);
|
||||
},
|
||||
});
|
||||
|
||||
const action = ctx.disposableStore.add(new Action('sessions.action.updateWidget', 'Sessions Update'));
|
||||
const widget = instantiationService.createInstance(UpdateWidget, action, {});
|
||||
ctx.disposableStore.add(widget);
|
||||
widget.render(ctx.container);
|
||||
}
|
||||
|
||||
export default defineThemedFixtureGroup({
|
||||
Ready: defineComponentFixture({
|
||||
render: (ctx) => renderUpdateWidget(ctx, State.Ready(mockUpdate, true, false)),
|
||||
}),
|
||||
|
||||
CheckingForUpdates: defineComponentFixture({
|
||||
render: (ctx) => renderUpdateWidget(ctx, State.CheckingForUpdates(true)),
|
||||
}),
|
||||
|
||||
AvailableForDownload: defineComponentFixture({
|
||||
render: (ctx) => renderUpdateWidget(ctx, State.AvailableForDownload(mockUpdate)),
|
||||
}),
|
||||
|
||||
Downloading0Percent: defineComponentFixture({
|
||||
render: (ctx) => renderUpdateWidget(ctx, State.Downloading(mockUpdate, true, false, 0, 100_000_000)),
|
||||
}),
|
||||
|
||||
Downloading30Percent: defineComponentFixture({
|
||||
render: (ctx) => renderUpdateWidget(ctx, State.Downloading(mockUpdate, true, false, 30_000_000, 100_000_000)),
|
||||
}),
|
||||
|
||||
Downloading65Percent: defineComponentFixture({
|
||||
render: (ctx) => renderUpdateWidget(ctx, State.Downloading(mockUpdate, true, false, 65_000_000, 100_000_000)),
|
||||
}),
|
||||
|
||||
Downloading100Percent: defineComponentFixture({
|
||||
render: (ctx) => renderUpdateWidget(ctx, State.Downloading(mockUpdate, true, false, 100_000_000, 100_000_000)),
|
||||
}),
|
||||
|
||||
DownloadingIndeterminate: defineComponentFixture({
|
||||
render: (ctx) => renderUpdateWidget(ctx, State.Downloading(mockUpdate, true, false)),
|
||||
}),
|
||||
|
||||
Downloaded: defineComponentFixture({
|
||||
render: (ctx) => renderUpdateWidget(ctx, State.Downloaded(mockUpdate, true, false)),
|
||||
}),
|
||||
|
||||
Updating: defineComponentFixture({
|
||||
render: (ctx) => renderUpdateWidget(ctx, State.Updating(mockUpdate)),
|
||||
}),
|
||||
|
||||
Overwriting: defineComponentFixture({
|
||||
render: (ctx) => renderUpdateWidget(ctx, State.Overwriting(mockUpdate, true)),
|
||||
}),
|
||||
});
|
||||
Reference in New Issue
Block a user