Skip to content

Commit

Permalink
feat: new window watermark (#87)
Browse files Browse the repository at this point in the history
  • Loading branch information
Himanshu-Singh-Chauhan authored and nang-dev committed Nov 6, 2024
1 parent 94841c5 commit 295847f
Show file tree
Hide file tree
Showing 3 changed files with 275 additions and 36 deletions.
146 changes: 130 additions & 16 deletions src/vs/workbench/browser/parts/editor/editorGroupWatermark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@ import { isMacintosh, isWeb, OS } from 'vs/base/common/platform';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { append, clearNode, $, h } from 'vs/base/browser/dom';
import { append, clearNode, $, h, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { ContextKeyExpr, ContextKeyExpression, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { defaultKeybindingLabelStyles } from 'vs/platform/theme/browser/defaultStyles';
import { editorForeground, registerColor, transparent } from 'vs/platform/theme/common/colorRegistry';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { isRecentFolder, IWorkspacesService } from 'vs/platform/workspaces/common/workspaces';
import { IWindowOpenable } from 'vs/platform/window/common/window';
import { ILabelService, Verbosity } from 'vs/platform/label/common/label';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { splitRecentLabel } from 'vs/base/common/labels';

registerColor('editorWatermark.foreground', { dark: transparent(editorForeground, 0.6), light: transparent(editorForeground, 0.68), hcDark: editorForeground, hcLight: editorForeground }, localize('editorLineHighlight', 'Foreground color for the labels in the editor watermark.'));

Expand All @@ -26,7 +31,7 @@ interface WatermarkEntry {
readonly when?: ContextKeyExpression;
}

const openPearAIChat: WatermarkEntry = { text: localize('watermark.openPearAIChat', "Open Chat"), id: 'pearai.focusContinueInput', when: ContextKeyExpr.has('pearAIExtensionLoaded') };
const openPearAIChat: WatermarkEntry = { text: localize('watermark.openPearAIChat', "Open Chat"), id: 'pearai.focusContinueInput', when: ContextKeyExpr.has('pearAIExtensionLoaded') };
const bigChat: WatermarkEntry = { text: localize('watermark.pearAIBigChat', "Big Chat"), id: 'pearai.resizeAuxiliaryBarWidth', when: ContextKeyExpr.has('pearAIExtensionLoaded') };
const prevChat: WatermarkEntry = { text: localize('watermark.pearAIPrevChat', "Previous Chat"), id: 'pearai.loadRecentChat', when: ContextKeyExpr.has('pearAIExtensionLoaded') };
const showCommands: WatermarkEntry = { text: localize('watermark.showCommands', "Show All Commands"), id: 'workbench.action.showCommands' };
Expand Down Expand Up @@ -68,7 +73,7 @@ const folderEntries = [
];

export class EditorGroupWatermark extends Disposable {
private readonly shortcuts: HTMLElement;
private readonly watermark: HTMLElement;
private readonly transientDisposables = this._register(new DisposableStore());
private enabled: boolean = false;
private workbenchState: WorkbenchState;
Expand All @@ -80,21 +85,21 @@ export class EditorGroupWatermark extends Disposable {
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IExtensionService private readonly extensionService: IExtensionService
@IExtensionService private readonly extensionService: IExtensionService,
@IWorkspacesService private readonly workspacesService: IWorkspacesService,
@ILabelService private readonly labelService: ILabelService,
@IHostService private readonly hostService: IHostService,
@ICommandService private readonly commandService: ICommandService
) {
super();
this.workbenchState = contextService.getWorkbenchState();
const hasWorkspace = this.workbenchState !== WorkbenchState.EMPTY;

const elements = h('.editor-group-watermark', [
h('.letterpress'),
h('.shortcuts@shortcuts'),
]);
const elements = h('.editor-group-watermark-' + (hasWorkspace ? 'workspace' : 'no-workspace'));

append(container, elements.root);
this.shortcuts = elements.shortcuts;

this.watermark = elements.root;
this.registerListeners();

this.workbenchState = contextService.getWorkbenchState();
this.render();
}

Expand Down Expand Up @@ -127,7 +132,7 @@ export class EditorGroupWatermark extends Disposable {
private async render(): Promise<void> {
// Wait for the all extensions to be activated
await this.extensionService.activateByEvent('onStartupFinished');
// TODO: @Himanshu-Singh-Chauhan - this should be set from inside the extension, test it later, if it works, remove this
// TODO: @Himanshu-Singh-Chauhan - this should be set from inside the extension, test it later, if it works, remove this
this.contextKeyService.createKey('pearAIExtensionLoaded', true); // Set a context key when the PearAI extension is loaded

const enabled = this.configurationService.getValue<boolean>('workbench.tips.enabled');
Expand All @@ -143,7 +148,16 @@ export class EditorGroupWatermark extends Disposable {
return;
}

const box = append(this.shortcuts, $('.watermark-box'));
const hasWorkspace = this.workbenchState !== WorkbenchState.EMPTY;

if (!hasWorkspace) {
this.renderNoWorkspaceWatermark();
return;
}

append(this.watermark, $('.letterpress'));
const shortcuts = append(this.watermark, $('.shortcuts'));
const box = append(shortcuts, $('.watermark-box'));
const folder = this.workbenchState !== WorkbenchState.EMPTY;
const selected = (folder ? folderEntries : noFolderEntries)
.filter(entry => !('when' in entry) || this.contextKeyService.contextMatchesRules(entry.when))
Expand Down Expand Up @@ -175,8 +189,108 @@ export class EditorGroupWatermark extends Disposable {
this.transientDisposables.add(this.keybindingService.onDidUpdateKeybindings(update));
}

private async renderNoWorkspaceWatermark(): Promise<void> {
const container = append(this.watermark, $('.editor-group-watermark-no-workspace'));

// button container
const buttonContainer = append(container, $('.button-container'));
const openFolderButton = append(buttonContainer, $('button.open-folder-button'));
// folder icon and text in separate spans
append(openFolderButton, $('span.codicon.codicon-folder-opened'));
append(openFolderButton, $('span.text', {}, localize('watermark.openFolder', "Open Folder")));
// click handler for Open Folder button
this._register(addDisposableListener(openFolderButton, EventType.CLICK, (e: MouseEvent) => {
e.preventDefault();
e.stopPropagation();
this.commandService.executeCommand('workbench.action.files.openFolder');
}));

// New File text button
const newFileItem = append(container, $('.new-file-item'));
newFileItem.textContent = localize('watermark.newFile', "New File");
newFileItem.style.cursor = 'pointer';

const newFileKeybinding = this.keybindingService.lookupKeybinding('workbench.action.files.newUntitledFile')?.getLabel();
newFileItem.title = newFileKeybinding ?
localize('watermark.newFileWithKeybinding', "New File ({0})", newFileKeybinding) :
localize('watermark.newFile', "New File");

this._register(addDisposableListener(newFileItem, EventType.CLICK, (e: MouseEvent) => {
e.preventDefault();
e.stopPropagation();
this.commandService.executeCommand('workbench.action.files.newUntitledFile');
}));

// recent folders and workspaces list
const recentList = append(container, $('.recent-list'));

const recentlyOpened = await this.workspacesService.getRecentlyOpened();
const recents = recentlyOpened.workspaces
.filter(recent => !this.contextService.isCurrentWorkspace(
isRecentFolder(recent) ? recent.folderUri : recent.workspace.configPath
))
.slice(0, 6);

if (recents.length === 0) {
const noRecentsElement = append(recentList, $('.recent-item'));
noRecentsElement.textContent = localize('watermark.noRecents', "No Recent Folders");
return;
}

recents.forEach(recent => {
const itemElement = append(recentList, $('.recent-item'));

let fullPath: string;
let windowOpenable: IWindowOpenable;

if (isRecentFolder(recent)) {
windowOpenable = { folderUri: recent.folderUri };
fullPath = recent.label || this.labelService.getWorkspaceLabel(recent.folderUri, { verbose: Verbosity.LONG });
} else {
fullPath = recent.label || this.labelService.getWorkspaceLabel(recent.workspace, { verbose: Verbosity.LONG });
windowOpenable = { workspaceUri: recent.workspace.configPath };
}

const { name, parentPath } = splitRecentLabel(fullPath);

itemElement.textContent = name;
if (parentPath) {
append(itemElement, $('span.spacer'));
const pathSpan = append(itemElement, $('span.path'));
pathSpan.textContent = parentPath;
}

itemElement.title = fullPath;
itemElement.style.cursor = 'pointer';

this._register(addDisposableListener(itemElement, EventType.CLICK, async (e: MouseEvent) => {
try {
e.preventDefault();
e.stopPropagation();
await this.hostService.openWindow([windowOpenable], {
forceNewWindow: e.ctrlKey || e.metaKey,
remoteAuthority: recent.remoteAuthority ?? null
});
} catch (error) {
console.error('Failed to open recent item:', error);
}
}));
});

// "More..." item
const moreItem = append(recentList, $('.more-item'));
moreItem.textContent = localize('watermark.more', "More...");
moreItem.title = localize('watermark.showMoreRecents', "Show All Recent Folders");
moreItem.style.cursor = 'pointer';
this._register(addDisposableListener(moreItem, EventType.CLICK, (e: MouseEvent) => {
e.preventDefault();
e.stopPropagation();
this.commandService.executeCommand('workbench.action.openRecent');
}));
}

private clear(): void {
clearNode(this.shortcuts);
clearNode(this.watermark);
this.transientDisposables.clear();
}

Expand Down
Loading

0 comments on commit 295847f

Please sign in to comment.