From dfcf5c1528b7de7b3e7664f9183a5f9d1e4508cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Moreno?= Date: Mon, 2 Jan 2023 17:23:45 +0100 Subject: [PATCH] move watermark shortcuts closer to letterpress (#170403) * move watermark shortcuts closer to letterpress fixes #59952 * fix layout in firefox --- .../browser/parts/editor/editorGroupView.ts | 20 +- .../parts/editor/editorGroupWatermark.ts | 178 ++++++++++++++ .../parts/editor/media/editorgroupview.css | 105 +++++++-- .../browser/workbench.contribution.ts | 5 + .../watermark/browser/media/watermark.css | 76 ------ .../contrib/watermark/browser/watermark.ts | 220 ------------------ src/vs/workbench/workbench.common.main.ts | 3 - 7 files changed, 278 insertions(+), 329 deletions(-) create mode 100644 src/vs/workbench/browser/parts/editor/editorGroupWatermark.ts delete mode 100644 src/vs/workbench/contrib/watermark/browser/media/watermark.css delete mode 100644 src/vs/workbench/contrib/watermark/browser/watermark.ts diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts index 1d5d4963cab..a8f0d1b8b50 100644 --- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts +++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts @@ -11,7 +11,7 @@ import { EditorInput } from 'vs/workbench/common/editor/editorInput'; import { SideBySideEditorInput } from 'vs/workbench/common/editor/sideBySideEditorInput'; import { Emitter, Relay } from 'vs/base/common/event'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor, asCSSUrl, IDomNodePagePosition } from 'vs/base/browser/dom'; +import { Dimension, trackFocus, addDisposableListener, EventType, EventHelper, findParentWithClass, clearNode, isAncestor, IDomNodePagePosition } from 'vs/base/browser/dom'; import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar'; @@ -43,7 +43,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic import { hash } from 'vs/base/common/hash'; import { getMimeTypes } from 'vs/editor/common/services/languagesAssociations'; import { extname, isEqual } from 'vs/base/common/resources'; -import { AppResourcePath, FileAccess, Schemas } from 'vs/base/common/network'; +import { Schemas } from 'vs/base/common/network'; import { EditorActivation, IEditorOptions } from 'vs/platform/editor/common/editor'; import { IFileDialogService, ConfirmResult } from 'vs/platform/dialogs/common/dialogs'; import { IFilesConfigurationService, AutoSaveMode } from 'vs/workbench/services/filesConfiguration/common/filesConfigurationService'; @@ -55,6 +55,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { TrustedTelemetryValue } from 'vs/platform/telemetry/common/telemetryUtils'; import { defaultProgressBarStyles } from 'vs/platform/theme/browser/defaultStyles'; import { IBoundarySashes } from 'vs/base/browser/ui/sash/sash'; +import { EditorGroupWatermark } from 'vs/workbench/browser/parts/editor/editorGroupWatermark'; export class EditorGroupView extends Themable implements IEditorGroupView { @@ -178,10 +179,8 @@ export class EditorGroupView extends Themable implements IEditorGroupView { // Container context menu this.createContainerContextMenu(); - // Letterpress container - const letterpressContainer = document.createElement('div'); - letterpressContainer.classList.add('editor-group-letterpress'); - this.element.appendChild(letterpressContainer); + // Watermark & shortcuts + this._register(this.instantiationService.createInstance(EditorGroupWatermark, this.element)); // Progress bar this.progressBar = this._register(new ProgressBar(this.element, defaultProgressBarStyles)); @@ -1904,6 +1903,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView { layout(width: number, height: number, top: number, left: number): void { this.lastLayout = { width, height, top, left }; + this.element.classList.toggle('max-height-478px', height <= 478); // Layout the title area first to receive the size it occupies const titleAreaSize = this.titleAreaControl.layout({ @@ -1953,14 +1953,6 @@ export interface EditorReplacement extends IEditorReplacement { registerThemingParticipant((theme, collector) => { - // Letterpress - const letterpress: AppResourcePath = `vs/workbench/browser/parts/editor/media/letterpress-${theme.type}.svg`; - collector.addRule(` - .monaco-workbench .part.editor > .content .editor-group-container.empty .editor-group-letterpress { - background-image: ${asCSSUrl(FileAccess.asBrowserUri(letterpress))} - } - `); - // Focused Empty Group Border const focusedEmptyGroupBorder = theme.getColor(EDITOR_GROUP_FOCUSED_EMPTY_BORDER); if (focusedEmptyGroupBorder) { diff --git a/src/vs/workbench/browser/parts/editor/editorGroupWatermark.ts b/src/vs/workbench/browser/parts/editor/editorGroupWatermark.ts new file mode 100644 index 00000000000..7f849060117 --- /dev/null +++ b/src/vs/workbench/browser/parts/editor/editorGroupWatermark.ts @@ -0,0 +1,178 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; +import { isMacintosh, isWeb, OS } from 'vs/base/common/platform'; +import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; +import * as nls from 'vs/nls'; +import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; +import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { append, clearNode, $, h } from 'vs/base/browser/dom'; +import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel'; +import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { ContextKeyExpr, ContextKeyExpression, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; +import { defaultKeybindingLabelStyles } from 'vs/platform/theme/browser/defaultStyles'; + +interface WatermarkEntry { + text: string; + id: string; + mac?: boolean; + when?: ContextKeyExpression; +} + +const showCommands: WatermarkEntry = { text: nls.localize('watermark.showCommands', "Show All Commands"), id: 'workbench.action.showCommands' }; +const quickAccess: WatermarkEntry = { text: nls.localize('watermark.quickAccess', "Go to File"), id: 'workbench.action.quickOpen' }; +const openFileNonMacOnly: WatermarkEntry = { text: nls.localize('watermark.openFile', "Open File"), id: 'workbench.action.files.openFile', mac: false }; +const openFolderNonMacOnly: WatermarkEntry = { text: nls.localize('watermark.openFolder', "Open Folder"), id: 'workbench.action.files.openFolder', mac: false }; +const openFileOrFolderMacOnly: WatermarkEntry = { text: nls.localize('watermark.openFileFolder', "Open File or Folder"), id: 'workbench.action.files.openFileFolder', mac: true }; +const openRecent: WatermarkEntry = { text: nls.localize('watermark.openRecent', "Open Recent"), id: 'workbench.action.openRecent' }; +const newUntitledFile: WatermarkEntry = { text: nls.localize('watermark.newUntitledFile', "New Untitled Text File"), id: 'workbench.action.files.newUntitledFile' }; +const newUntitledFileMacOnly: WatermarkEntry = Object.assign({ mac: true }, newUntitledFile); +const findInFiles: WatermarkEntry = { text: nls.localize('watermark.findInFiles', "Find in Files"), id: 'workbench.action.findInFiles' }; +const toggleTerminal: WatermarkEntry = { text: nls.localize({ key: 'watermark.toggleTerminal', comment: ['toggle is a verb here'] }, "Toggle Terminal"), id: 'workbench.action.terminal.toggleTerminal', when: ContextKeyExpr.equals('terminalProcessSupported', true) }; +const startDebugging: WatermarkEntry = { text: nls.localize('watermark.startDebugging', "Start Debugging"), id: 'workbench.action.debug.start', when: ContextKeyExpr.equals('terminalProcessSupported', true) }; +const toggleFullscreen: WatermarkEntry = { text: nls.localize({ key: 'watermark.toggleFullscreen', comment: ['toggle is a verb here'] }, "Toggle Full Screen"), id: 'workbench.action.toggleFullScreen', when: ContextKeyExpr.equals('terminalProcessSupported', true).negate() }; +const showSettings: WatermarkEntry = { text: nls.localize('watermark.showSettings', "Show Settings"), id: 'workbench.action.openSettings', when: ContextKeyExpr.equals('terminalProcessSupported', true).negate() }; + +const noFolderEntries = [ + showCommands, + openFileNonMacOnly, + openFolderNonMacOnly, + openFileOrFolderMacOnly, + openRecent, + newUntitledFileMacOnly +]; + +const folderEntries = [ + showCommands, + quickAccess, + findInFiles, + startDebugging, + toggleTerminal, + toggleFullscreen, + showSettings +]; + +export class EditorGroupWatermark extends Disposable { + + private readonly shortcuts: HTMLElement; + private transientDisposables = this._register(new DisposableStore()); + private enabled: boolean; + private workbenchState: WorkbenchState; + + constructor( + container: HTMLElement, + @ILifecycleService private readonly lifecycleService: ILifecycleService, + @IKeybindingService private readonly keybindingService: IKeybindingService, + @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, + @IContextKeyService private readonly contextKeyService: IContextKeyService, + @IConfigurationService private readonly configurationService: IConfigurationService, + @ITelemetryService private readonly telemetryService: ITelemetryService + ) { + super(); + + const elements = h('.editor-group-watermark', [ + h('.letterpress'), + h('.shortcuts@shortcuts'), + ]); + + append(container, elements.root); + this.shortcuts = elements.shortcuts; + + this.workbenchState = contextService.getWorkbenchState(); + this.enabled = this.configurationService.getValue('workbench.tips.enabled'); + + this.registerListeners(); + + if (this.enabled) { + this.render(); + } + } + + private registerListeners(): void { + this.lifecycleService.onDidShutdown(() => this.dispose()); + + this._register(this.configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('workbench.tips.enabled')) { + const enabled = this.configurationService.getValue('workbench.tips.enabled'); + + if (enabled === this.enabled) { + return; + } + + this.enabled = enabled; + + if (this.enabled) { + this.render(); + } else { + this.clear(); + } + } + })); + + this._register(this.contextService.onDidChangeWorkbenchState(workbenchState => { + if (!this.enabled || this.workbenchState === workbenchState) { + return; + } + + this.workbenchState = workbenchState; + this.render(); + })); + + const allEntriesWhenClauses = [...noFolderEntries, ...folderEntries].filter(entry => entry.when !== undefined).map(entry => entry.when!); + const allKeys = new Set(); + allEntriesWhenClauses.forEach(when => when.keys().forEach(key => allKeys.add(key))); + this._register(this.contextKeyService.onDidChangeContext(e => { + if (e.affectsSome(allKeys)) { + this.render(); + } + })); + } + + private render(): void { + this.clear(); + + const box = append(this.shortcuts, $('.watermark-box')); + const folder = this.workbenchState !== WorkbenchState.EMPTY; + const selected = (folder ? folderEntries : noFolderEntries) + .filter(entry => !('when' in entry) || this.contextKeyService.contextMatchesRules(entry.when)) + .filter(entry => !('mac' in entry) || entry.mac === (isMacintosh && !isWeb)) + .filter(entry => !!CommandsRegistry.getCommand(entry.id)); + + const update = () => { + clearNode(box); + selected.map(entry => { + const dl = append(box, $('dl')); + const dt = append(dl, $('dt')); + dt.textContent = entry.text; + const dd = append(dl, $('dd')); + const keybinding = new KeybindingLabel(dd, OS, { renderUnboundKeybindings: true, ...defaultKeybindingLabelStyles }); + keybinding.set(this.keybindingService.lookupKeybinding(entry.id)); + }); + }; + + update(); + this.transientDisposables.add(this.keybindingService.onDidUpdateKeybindings(update)); + + /* __GDPR__ + "watermark:open" : { + "owner": "digitarald" + } + */ + this.telemetryService.publicLog('watermark:open'); + } + + private clear(): void { + clearNode(this.shortcuts); + this.transientDisposables.clear(); + } + + override dispose(): void { + super.dispose(); + this.clear(); + } +} diff --git a/src/vs/workbench/browser/parts/editor/media/editorgroupview.css b/src/vs/workbench/browser/parts/editor/media/editorgroupview.css index a7a0673068d..a4a46ddb6aa 100644 --- a/src/vs/workbench/browser/parts/editor/media/editorgroupview.css +++ b/src/vs/workbench/browser/parts/editor/media/editorgroupview.css @@ -18,28 +18,101 @@ opacity: 1; /* indicate active/dragged-over group through undimmed state */ } -/* Letterpress */ +/* Watermark & shortcuts */ -.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-letterpress { - display: none; /* only visible when empty */ -} - -.monaco-workbench .part.editor > .content .editor-group-container.empty > .editor-group-letterpress { - display: block; +.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-watermark { + display: flex; + height: 100%; + max-width: 290px; margin: auto; - width: 100%; - height: calc(100% - 70px); /* centered below toolbar */ - max-width: 260px; - background-repeat: no-repeat; - background-position: 50% 50%; - background-size: 70% 70%; + flex-direction: column; + align-items: center; + justify-content: center; } -.monaco-workbench .part.editor > .content.empty .editor-group-container.empty > .editor-group-letterpress { - background-size: 100% 100%; /* larger for empty editor part */ - height: 100%; /* no toolbar in this case */ +.monaco-workbench .part.editor > .content .editor-group-container:not(.empty) > .editor-group-watermark { + display: none; } +.monaco-workbench .part.editor > .content:not(.empty) .editor-group-container.empty > .editor-group-watermark { + max-width: 200px; + height: calc(100% - 35px); +} + +.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-watermark > .letterpress { + width: 100%; + max-height: 100%; + aspect-ratio: 1/1; + background-image: url('./letterpress-light.svg'); + background-position-x: center; + background-repeat: no-repeat; +} + +.monaco-workbench.vs-dark .part.editor > .content .editor-group-container .editor-group-watermark > .letterpress { + background-image: url('./letterpress-dark.svg'); +} + +.monaco-workbench.hc-light .part.editor > .content .editor-group-container .editor-group-watermark > .letterpress { + background-image: url('./letterpress-hcLight.svg'); +} + +.monaco-workbench.hc-black .part.editor > .content .editor-group-container .editor-group-watermark > .letterpress { + background-image: url('./letterpress-hcDark.svg'); +} + +.monaco-workbench .part.editor > .content:not(.empty) .editor-group-container > .editor-group-watermark > .shortcuts, +.monaco-workbench .part.editor > .content .editor-group-container.max-height-478px > .editor-group-watermark > .shortcuts { + display: none; +} + +.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-watermark > .shortcuts > .watermark-box { + display: inline-table; + border-collapse: separate; + border-spacing: 11px 17px; +} + +.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-watermark > .shortcuts dl { + display: table-row; + opacity: .8; + cursor: default; +} + +.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-watermark > .shortcuts dt { + text-align: right; + letter-spacing: 0.04em +} + +.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-watermark > .shortcuts dd { + text-align: left; +} + +.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-watermark > .shortcuts dt, +.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-watermark > .shortcuts dd { + display: table-cell; + vertical-align: middle; +} + +.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-watermark > .shortcuts dt, +.monaco-workbench .part.editor > .content .editor-group-container > .editor-group-watermark > .shortcuts dl { + color: rgba(0,0,0,.68); +} + +.monaco-workbench.vs-dark .part.editor > .content .editor-group-container .editor-group-watermark > .shortcuts dt, +.monaco-workbench.vs-dark .part.editor > .content .editor-group-container .editor-group-watermark > .shortcuts dl { + color: rgba(255,255,255,.6); +} + +.monaco-workbench.hc-black .part.editor > .content .editor-group-container .editor-group-watermark > .shortcuts dt, +.monaco-workbench.hc-light .part.editor > .content .editor-group-container .editor-group-watermark > .shortcuts dt { + color: var(--vscode-editor-foreground); +} +.monaco-workbench.hc-black .part.editor > .content .editor-group-container .editor-group-watermark > .shortcuts dl, +.monaco-workbench.hc-light .part.editor > .content .editor-group-container .editor-group-watermark > .shortcuts dl { + color: var(--vscode-editor-foreground); + opacity: 1; +} + + /* Title */ .monaco-workbench .part.editor > .content .editor-group-container > .title { diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts index 2d2eb4b0df9..abfd3a12a31 100644 --- a/src/vs/workbench/browser/workbench.contribution.ts +++ b/src/vs/workbench/browser/workbench.contribution.ts @@ -469,6 +469,11 @@ const registry = Registry.as(ConfigurationExtensions.Con 'default': 'both', 'description': localize('layoutControlType', "Controls whether the layout control in the custom title bar is displayed as a single menu button or with multiple UI toggles."), }, + 'workbench.tips.enabled': { + 'type': 'boolean', + 'default': true, + 'description': localize('tips.enabled', "When enabled, will show the watermark tips when no editor is open.") + }, } }); diff --git a/src/vs/workbench/contrib/watermark/browser/media/watermark.css b/src/vs/workbench/contrib/watermark/browser/media/watermark.css deleted file mode 100644 index 2c45ebd4b16..00000000000 --- a/src/vs/workbench/contrib/watermark/browser/media/watermark.css +++ /dev/null @@ -1,76 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -.monaco-workbench .part.editor.has-watermark > .content.empty .editor-group-container > .editor-group-letterpress { - background-position-y: calc(50% - 100px); -} - -.monaco-workbench .part.editor.max-height-478px > .content.empty .editor-group-container > .editor-group-letterpress { - background-position-y: 50%; -} - -.monaco-workbench .part.editor > .content > .watermark { - display: none; /* only visible when no editors are opened */ -} - -.monaco-workbench .part.editor.has-watermark > .content.empty > .watermark { - display: block; - position: absolute; - width: 100%; - top: calc(50% + 55px); - text-align: center; - white-space: nowrap; - overflow: hidden; -} - -.monaco-workbench .part.editor > .content.empty > .watermark > .watermark-box { - display: inline-table; - border-collapse: separate; - border-spacing: 13px 17px; -} - -.monaco-workbench .part.editor.max-height-478px > .content.empty > .watermark { - display: none; -} - -.monaco-workbench .part.editor > .content.empty > .watermark dl { - display: table-row; - opacity: .8; - cursor: default; -} - -.monaco-workbench .part.editor > .content.empty > .watermark dt { - text-align: right; - letter-spacing: 0.04em -} - -.monaco-workbench .part.editor > .content.empty > .watermark dd { - text-align: left; -} - -.monaco-workbench .part.editor > .content.empty > .watermark dt, -.monaco-workbench .part.editor > .content.empty > .watermark dd { - display: table-cell; -} - -.monaco-workbench .part.editor > .content.empty > .watermark dt, -.monaco-workbench .part.editor > .content.empty > .watermark dl { - color: rgba(0,0,0,.68); -} - -.monaco-workbench.vs-dark .part.editor > .content.empty > .watermark dt, -.monaco-workbench.vs-dark .part.editor > .content.empty > .watermark dl { - color: rgba(255,255,255,.6); -} - -.monaco-workbench.hc-black .part.editor > .content.empty > .watermark dt, -.monaco-workbench.hc-light .part.editor > .content.empty > .watermark dt { - color: var(--vscode-editor-foreground); -} -.monaco-workbench.hc-black .part.editor > .content.empty > .watermark dl, -.monaco-workbench.hc-light .part.editor > .content.empty > .watermark dl { - color: var(--vscode-editor-foreground); - opacity: 1; -} diff --git a/src/vs/workbench/contrib/watermark/browser/watermark.ts b/src/vs/workbench/contrib/watermark/browser/watermark.ts deleted file mode 100644 index a7cca4975c6..00000000000 --- a/src/vs/workbench/contrib/watermark/browser/watermark.ts +++ /dev/null @@ -1,220 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import 'vs/css!./media/watermark'; -import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; -import { isMacintosh, isWeb, OS } from 'vs/base/common/platform'; -import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; -import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import * as nls from 'vs/nls'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { OpenFolderAction, OpenFileFolderAction, OpenFileAction } from 'vs/workbench/browser/actions/workspaceActions'; -import { OpenRecentAction } from 'vs/workbench/browser/actions/windowActions'; -import { ShowAllCommandsAction } from 'vs/workbench/contrib/quickaccess/browser/commandsQuickAccess'; -import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; -import { FindInFilesActionId } from 'vs/workbench/contrib/search/common/constants'; -import * as dom from 'vs/base/browser/dom'; -import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel'; -import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; -import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; -import { assertIsDefined } from 'vs/base/common/types'; -import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration'; -import { NEW_UNTITLED_FILE_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileConstants'; -import { DEBUG_START_COMMAND_ID } from 'vs/workbench/contrib/debug/browser/debugCommands'; -import { ContextKeyExpression, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; -import { TerminalContextKeys } from 'vs/workbench/contrib/terminal/common/terminalContextKey'; -import { defaultKeybindingLabelStyles } from 'vs/platform/theme/browser/defaultStyles'; - -const $ = dom.$; - -interface WatermarkEntry { - text: string; - id: string; - mac?: boolean; - when?: ContextKeyExpression; -} - -const showCommands: WatermarkEntry = { text: nls.localize('watermark.showCommands', "Show All Commands"), id: ShowAllCommandsAction.ID }; -const quickAccess: WatermarkEntry = { text: nls.localize('watermark.quickAccess', "Go to File"), id: 'workbench.action.quickOpen' }; -const openFileNonMacOnly: WatermarkEntry = { text: nls.localize('watermark.openFile', "Open File"), id: OpenFileAction.ID, mac: false }; -const openFolderNonMacOnly: WatermarkEntry = { text: nls.localize('watermark.openFolder', "Open Folder"), id: OpenFolderAction.ID, mac: false }; -const openFileOrFolderMacOnly: WatermarkEntry = { text: nls.localize('watermark.openFileFolder', "Open File or Folder"), id: OpenFileFolderAction.ID, mac: true }; -const openRecent: WatermarkEntry = { text: nls.localize('watermark.openRecent', "Open Recent"), id: OpenRecentAction.ID }; -const newUntitledFile: WatermarkEntry = { text: nls.localize('watermark.newUntitledFile', "New Untitled Text File"), id: NEW_UNTITLED_FILE_COMMAND_ID }; -const newUntitledFileMacOnly: WatermarkEntry = Object.assign({ mac: true }, newUntitledFile); -const findInFiles: WatermarkEntry = { text: nls.localize('watermark.findInFiles', "Find in Files"), id: FindInFilesActionId }; -const toggleTerminal: WatermarkEntry = { text: nls.localize({ key: 'watermark.toggleTerminal', comment: ['toggle is a verb here'] }, "Toggle Terminal"), id: TerminalCommandId.Toggle, when: TerminalContextKeys.processSupported }; -const startDebugging: WatermarkEntry = { text: nls.localize('watermark.startDebugging', "Start Debugging"), id: DEBUG_START_COMMAND_ID, when: TerminalContextKeys.processSupported }; -const toggleFullscreen: WatermarkEntry = { text: nls.localize({ key: 'watermark.toggleFullscreen', comment: ['toggle is a verb here'] }, "Toggle Full Screen"), id: 'workbench.action.toggleFullScreen', when: TerminalContextKeys.processSupported.toNegated() }; -const showSettings: WatermarkEntry = { text: nls.localize('watermark.showSettings', "Show Settings"), id: 'workbench.action.openSettings', when: TerminalContextKeys.processSupported.toNegated() }; - -const noFolderEntries = [ - showCommands, - openFileNonMacOnly, - openFolderNonMacOnly, - openFileOrFolderMacOnly, - openRecent, - newUntitledFileMacOnly -]; - -const folderEntries = [ - showCommands, - quickAccess, - findInFiles, - startDebugging, - toggleTerminal, - toggleFullscreen, - showSettings -]; - -const WORKBENCH_TIPS_ENABLED_KEY = 'workbench.tips.enabled'; - -export class WatermarkContribution extends Disposable implements IWorkbenchContribution { - private watermark: HTMLElement | undefined; - private watermarkDisposable = this._register(new DisposableStore()); - private enabled: boolean; - private workbenchState: WorkbenchState; - - constructor( - @ILifecycleService private readonly lifecycleService: ILifecycleService, - @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, - @IKeybindingService private readonly keybindingService: IKeybindingService, - @IWorkspaceContextService private readonly contextService: IWorkspaceContextService, - @IContextKeyService private readonly contextKeyService: IContextKeyService, - @IConfigurationService private readonly configurationService: IConfigurationService, - @IEditorGroupsService private readonly editorGroupsService: IEditorGroupsService, - @ITelemetryService private readonly telemetryService: ITelemetryService - ) { - super(); - - this.workbenchState = contextService.getWorkbenchState(); - this.enabled = this.configurationService.getValue(WORKBENCH_TIPS_ENABLED_KEY); - - this.registerListeners(); - - if (this.enabled) { - this.create(); - } - } - - private registerListeners(): void { - this.lifecycleService.onDidShutdown(() => this.dispose()); - - this._register(this.configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(WORKBENCH_TIPS_ENABLED_KEY)) { - const enabled = this.configurationService.getValue(WORKBENCH_TIPS_ENABLED_KEY); - if (enabled !== this.enabled) { - this.enabled = enabled; - if (this.enabled) { - this.create(); - } else { - this.destroy(); - } - } - } - })); - - this._register(this.contextService.onDidChangeWorkbenchState(e => { - const previousWorkbenchState = this.workbenchState; - this.workbenchState = this.contextService.getWorkbenchState(); - - if (this.enabled && this.workbenchState !== previousWorkbenchState) { - this.recreate(); - } - })); - - const allEntriesWhenClauses = [...noFolderEntries, ...folderEntries].filter(entry => entry.when !== undefined).map(entry => entry.when!); - const allKeys = new Set(); - allEntriesWhenClauses.forEach(when => when.keys().forEach(key => allKeys.add(key))); - this._register(this.contextKeyService.onDidChangeContext(e => { - if (e.affectsSome(allKeys)) { - this.recreate(); - } - })); - } - - private create(): void { - const container = assertIsDefined(this.layoutService.getContainer(Parts.EDITOR_PART)); - container.classList.add('has-watermark'); - - this.watermark = $('.watermark'); - const box = dom.append(this.watermark, $('.watermark-box')); - const folder = this.workbenchState !== WorkbenchState.EMPTY; - const selected = (folder ? folderEntries : noFolderEntries) - .filter(entry => !('when' in entry) || this.contextKeyService.contextMatchesRules(entry.when)) - .filter(entry => !('mac' in entry) || entry.mac === (isMacintosh && !isWeb)) - .filter(entry => !!CommandsRegistry.getCommand(entry.id)); - - - const update = () => { - dom.clearNode(box); - selected.map(entry => { - const dl = dom.append(box, $('dl')); - const dt = dom.append(dl, $('dt')); - dt.textContent = entry.text; - const dd = dom.append(dl, $('dd')); - const keybinding = new KeybindingLabel(dd, OS, { renderUnboundKeybindings: true, ...defaultKeybindingLabelStyles }); - keybinding.set(this.keybindingService.lookupKeybinding(entry.id)); - }); - }; - - update(); - - dom.prepend(container.firstElementChild as HTMLElement, this.watermark); - - this.watermarkDisposable.add(this.keybindingService.onDidUpdateKeybindings(update)); - this.watermarkDisposable.add(this.editorGroupsService.onDidLayout(dimension => this.handleEditorPartSize(container, dimension))); - - this.handleEditorPartSize(container, this.editorGroupsService.contentDimension); - - /* __GDPR__ - "watermark:open" : { - "owner": "digitarald" - } - */ - this.telemetryService.publicLog('watermark:open'); - } - - private handleEditorPartSize(container: HTMLElement, dimension: dom.IDimension): void { - container.classList.toggle('max-height-478px', dimension.height <= 478); - } - - private destroy(): void { - if (this.watermark) { - this.watermark.remove(); - - const container = this.layoutService.getContainer(Parts.EDITOR_PART); - container?.classList.remove('has-watermark'); - - this.watermarkDisposable.clear(); - } - } - - private recreate(): void { - this.destroy(); - this.create(); - } -} - -Registry.as(WorkbenchExtensions.Workbench) - .registerWorkbenchContribution(WatermarkContribution, LifecyclePhase.Restored); - -Registry.as(ConfigurationExtensions.Configuration) - .registerConfiguration({ - ...workbenchConfigurationNodeBase, - 'properties': { - 'workbench.tips.enabled': { - 'type': 'boolean', - 'default': true, - 'description': nls.localize('tips.enabled', "When enabled, will show the watermark tips when no editor is open.") - }, - } - }); diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index 6ef72fd96f4..e0c8d69815c 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -280,9 +280,6 @@ import 'vs/workbench/contrib/themes/browser/themes.contribution'; // Update import 'vs/workbench/contrib/update/browser/update.contribution'; -// Watermark -import 'vs/workbench/contrib/watermark/browser/watermark'; - // Surveys import 'vs/workbench/contrib/surveys/browser/nps.contribution'; import 'vs/workbench/contrib/surveys/browser/ces.contribution';