Skip to content

Commit

Permalink
upon create send over the list of existing status bar items and their…
Browse files Browse the repository at this point in the history
… props (#183219)

#167874
  • Loading branch information
jrieken authored May 23, 2023
1 parent 545faa5 commit b8559c1
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 30 deletions.
30 changes: 22 additions & 8 deletions src/vs/workbench/api/browser/mainThreadStatusBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,42 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { MainThreadStatusBarShape, MainContext } from '../common/extHost.protocol';
import { MainThreadStatusBarShape, MainContext, ExtHostContext, StatusBarItemDto } from '../common/extHost.protocol';
import { ThemeColor } from 'vs/base/common/themables';
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
import { DisposableMap } from 'vs/base/common/lifecycle';
import { Command } from 'vs/editor/common/languages';
import { IAccessibilityInformation } from 'vs/platform/accessibility/common/accessibility';
import { IMarkdownString } from 'vs/base/common/htmlContent';
import { IExtensionStatusBarItemService } from 'vs/workbench/api/browser/statusBarExtensionPoint';
import { StatusbarAlignment } from 'vs/workbench/services/statusbar/browser/statusbar';

@extHostNamedCustomer(MainContext.MainThreadStatusBar)
export class MainThreadStatusBar implements MainThreadStatusBarShape {

private readonly entries = new DisposableMap<string>();

constructor(
_extHostContext: IExtHostContext,
extHostContext: IExtHostContext,
@IExtensionStatusBarItemService private readonly statusbarService: IExtensionStatusBarItemService
) { }
) {
const proxy = extHostContext.getProxy(ExtHostContext.ExtHostStatusBar);

// once, at startup read existing items and send them over
const entries: StatusBarItemDto[] = [];
for (const [entryId, item] of statusbarService.getEntries()) {
entries.push({
entryId,
name: item.entry.name,
text: item.entry.text,
command: typeof item.entry.command === 'string' ? item.entry.command : undefined,
priority: item.priority,
alignLeft: item.alignment === StatusbarAlignment.LEFT
});
}

proxy.$acceptStaticEntries(entries);
}

dispose(): void {
this.entries.dispose();
Expand All @@ -33,11 +51,7 @@ export class MainThreadStatusBar implements MainThreadStatusBarShape {
}
}

async $hasEntry(entryId: string): Promise<boolean> {
return this.statusbarService.hasEntry(entryId);
}

$dispose(entryId: string) {
$disposeEntry(entryId: string) {
this.entries.deleteAndDispose(entryId);
}
}
15 changes: 11 additions & 4 deletions src/vs/workbench/api/browser/statusBarExtensionPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,25 @@ import { asStatusBarItemIdentifier } from 'vs/workbench/api/common/extHostTypes'

export const IExtensionStatusBarItemService = createDecorator<IExtensionStatusBarItemService>('IExtensionStatusBarItemService');

export interface IExtensionStatusBarItemChangeEvent {
readonly added?: Readonly<{ entryId: string } & IStatusbarEntry>;
readonly removed?: string;
}

export interface IExtensionStatusBarItemService {
readonly _serviceBrand: undefined;

setOrUpdateEntry(id: string, statusId: string, extensionId: string | undefined, name: string, text: string, tooltip: IMarkdownString | string | undefined, command: Command | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignLeft: boolean, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): IDisposable;

hasEntry(id: string): boolean;
getEntries(): Iterable<[string, { entry: IStatusbarEntry; alignment: MainThreadStatusBarAlignment; priority: number }]>;
}


class ExtensionStatusBarItemService implements IExtensionStatusBarItemService {

declare readonly _serviceBrand: undefined;

private readonly _entries: Map<string, { accessor: IStatusbarEntryAccessor; alignment: MainThreadStatusBarAlignment; priority: number }> = new Map();
private readonly _entries: Map<string, { accessor: IStatusbarEntryAccessor; entry: IStatusbarEntry; alignment: MainThreadStatusBarAlignment; priority: number }> = new Map();

constructor(@IStatusbarService private readonly _statusbarService: IStatusbarService) { }

Expand Down Expand Up @@ -88,13 +93,15 @@ class ExtensionStatusBarItemService implements IExtensionStatusBarItemService {

this._entries.set(entryId, {
accessor: this._statusbarService.addEntry(entry, id, alignment, entryPriority),
entry,
alignment,
priority
});

} else {
// Otherwise update
existingEntry.accessor.update(entry);
existingEntry.entry = entry;
}

return toDisposable(() => {
Expand All @@ -106,8 +113,8 @@ class ExtensionStatusBarItemService implements IExtensionStatusBarItemService {
});
}

hasEntry(id: string): boolean {
return this._entries.has(id);
getEntries(): Iterable<[string, { entry: IStatusbarEntry; alignment: MainThreadStatusBarAlignment; priority: number }]> {
return this._entries.entries();
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/api/common/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const extHostChat = rpcProtocol.set(ExtHostContext.ExtHostChat, new ExtHostChat(rpcProtocol, extHostLogService));
const extHostSemanticSimilarity = rpcProtocol.set(ExtHostContext.ExtHostSemanticSimilarity, new ExtHostSemanticSimilarity(rpcProtocol));
const extHostIssueReporter = rpcProtocol.set(ExtHostContext.ExtHostIssueReporter, new ExtHostIssueReporter(rpcProtocol));
const extHostStatusBar = rpcProtocol.set(ExtHostContext.ExtHostStatusBar, new ExtHostStatusBar(rpcProtocol, extHostCommands.converter));

// Check that no named customers are missing
const expected = Object.values<ProxyIdentifier<any>>(ExtHostContext);
Expand All @@ -216,7 +217,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
const extHostClipboard = new ExtHostClipboard(rpcProtocol);
const extHostMessageService = new ExtHostMessageService(rpcProtocol, extHostLogService);
const extHostDialogs = new ExtHostDialogs(rpcProtocol);
const extHostStatusBar = new ExtHostStatusBar(rpcProtocol, extHostCommands.converter);

// Register API-ish commands
ExtHostApiCommands.register(extHostCommands);
Expand Down
17 changes: 15 additions & 2 deletions src/vs/workbench/api/common/extHost.protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -614,9 +614,21 @@ export interface MainThreadQuickOpenShape extends IDisposable {
}

export interface MainThreadStatusBarShape extends IDisposable {
$hasEntry(id: string): Promise<boolean>;
$setEntry(id: string, statusId: string, extensionId: string | undefined, statusName: string, text: string, tooltip: IMarkdownString | string | undefined, command: ICommandDto | undefined, color: string | ThemeColor | undefined, backgroundColor: string | ThemeColor | undefined, alignLeft: boolean, priority: number | undefined, accessibilityInformation: IAccessibilityInformation | undefined): void;
$dispose(id: string): void;
$disposeEntry(id: string): void;
}

export type StatusBarItemDto = {
entryId: string;
alignLeft: boolean;
priority?: number;
name: string;
text: string;
command?: string;
};

export interface ExtHostStatusBarShape {
$acceptStaticEntries(added?: StatusBarItemDto[]): void;
}

export interface MainThreadStorageShape extends IDisposable {
Expand Down Expand Up @@ -2580,6 +2592,7 @@ export const ExtHostContext = {
ExtHostLanguageFeatures: createProxyIdentifier<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures'),
ExtHostQuickOpen: createProxyIdentifier<ExtHostQuickOpenShape>('ExtHostQuickOpen'),
ExtHostQuickDiff: createProxyIdentifier<ExtHostQuickDiffShape>('ExtHostQuickDiff'),
ExtHostStatusBar: createProxyIdentifier<ExtHostStatusBarShape>('ExtHostStatusBar'),
ExtHostShare: createProxyIdentifier<ExtHostShareShape>('ExtHostShare'),
ExtHostExtensionService: createProxyIdentifier<ExtHostExtensionServiceShape>('ExtHostExtensionService'),
ExtHostLogLevelServiceShape: createProxyIdentifier<ExtHostLogLevelServiceShape>('ExtHostLogLevelServiceShape'),
Expand Down
40 changes: 25 additions & 15 deletions src/vs/workbench/api/common/extHostStatusBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { StatusBarAlignment as ExtHostStatusBarAlignment, Disposable, ThemeColor, asStatusBarItemIdentifier } from './extHostTypes';
import type * as vscode from 'vscode';
import { MainContext, MainThreadStatusBarShape, IMainContext, ICommandDto } from './extHost.protocol';
import { MainContext, MainThreadStatusBarShape, IMainContext, ICommandDto, ExtHostStatusBarShape, StatusBarItemDto } from './extHost.protocol';
import { localize } from 'vs/nls';
import { CommandsConverter } from 'vs/workbench/api/common/extHostCommands';
import { DisposableStore } from 'vs/base/common/lifecycle';
Expand Down Expand Up @@ -54,22 +54,25 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
private _timeoutHandle: any;
private _accessibilityInformation?: vscode.AccessibilityInformation;

constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, extension: IExtensionDescription, id?: string, alignment?: ExtHostStatusBarAlignment, priority?: number);
constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, extension: IExtensionDescription | undefined, id: string, alignment?: ExtHostStatusBarAlignment, priority?: number);
constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, extension?: IExtensionDescription, id?: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number) {
constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, staticItems: ReadonlyMap<string, StatusBarItemDto>, extension: IExtensionDescription, id?: string, alignment?: ExtHostStatusBarAlignment, priority?: number);
constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, staticItems: ReadonlyMap<string, StatusBarItemDto>, extension: IExtensionDescription | undefined, id: string, alignment?: ExtHostStatusBarAlignment, priority?: number);
constructor(proxy: MainThreadStatusBarShape, commands: CommandsConverter, staticItems: ReadonlyMap<string, StatusBarItemDto>, extension?: IExtensionDescription, id?: string, alignment: ExtHostStatusBarAlignment = ExtHostStatusBarAlignment.Left, priority?: number) {
this.#proxy = proxy;
this.#commands = commands;

if (id && extension) {
this._entryId = asStatusBarItemIdentifier(extension.identifier, id);
proxy.$hasEntry(this._entryId).then(exits => {
if (exits && this._visible === undefined) {
// mark new item as visible if it already exists
// this can only happen when an item was contributed by an extension
this._visible = true;
this.update();
}
});
// if new item already exists mark it as visible and copy properties
// this can only happen when an item was contributed by an extension
const item = staticItems.get(this._entryId);
if (item) {
this._visible = true;
this._alignment = item.alignLeft ? ExtHostStatusBarAlignment.Left : ExtHostStatusBarAlignment.Right;
this._priority = item.priority;
this.name = item.name;
this.text = item.text;
this.command = item.command;
}
} else {
this._entryId = String(ExtHostStatusBarEntry.ID_GEN++);
}
Expand Down Expand Up @@ -208,7 +211,7 @@ export class ExtHostStatusBarEntry implements vscode.StatusBarItem {
public hide(): void {
clearTimeout(this._timeoutHandle);
this._visible = false;
this.#proxy.$dispose(this._entryId);
this.#proxy.$disposeEntry(this._entryId);
}

private update(): void {
Expand Down Expand Up @@ -307,22 +310,29 @@ class StatusBarMessage {
}
}

export class ExtHostStatusBar {
export class ExtHostStatusBar implements ExtHostStatusBarShape {

private readonly _proxy: MainThreadStatusBarShape;
private readonly _commands: CommandsConverter;
private readonly _statusMessage: StatusBarMessage;
private readonly _existingItems = new Map<string, StatusBarItemDto>();

constructor(mainContext: IMainContext, commands: CommandsConverter) {
this._proxy = mainContext.getProxy(MainContext.MainThreadStatusBar);
this._commands = commands;
this._statusMessage = new StatusBarMessage(this);
}

$acceptStaticEntries(added: StatusBarItemDto[]): void {
for (const item of added) {
this._existingItems.set(item.entryId, item);
}
}

createStatusBarEntry(extension: IExtensionDescription | undefined, id: string, alignment?: ExtHostStatusBarAlignment, priority?: number): vscode.StatusBarItem;
createStatusBarEntry(extension: IExtensionDescription, id?: string, alignment?: ExtHostStatusBarAlignment, priority?: number): vscode.StatusBarItem;
createStatusBarEntry(extension: IExtensionDescription, id: string, alignment?: ExtHostStatusBarAlignment, priority?: number): vscode.StatusBarItem {
return new ExtHostStatusBarEntry(this._proxy, this._commands, extension, id, alignment, priority);
return new ExtHostStatusBarEntry(this._proxy, this._commands, this._existingItems, extension, id, alignment, priority);
}

setStatusBarMessage(text: string, timeoutOrThenable?: number | Thenable<any>): Disposable {
Expand Down

0 comments on commit b8559c1

Please sign in to comment.