From 96d1e9300bceac30e54a301451fa44743fdf44fd Mon Sep 17 00:00:00 2001 From: Eric Amodio Date: Sun, 12 Nov 2023 01:14:29 -0500 Subject: [PATCH] Adds experimental editor layout for Cloud Patches --- package.json | 24 +++++++++++++ src/config.ts | 3 ++ src/constants.ts | 3 +- src/container.ts | 7 +++- .../webviews/patchDetails/patchDetailsWebview.ts | 36 +++++++++++++++++--- src/plus/webviews/patchDetails/registration.ts | 39 +++++++++++++++++++++- 6 files changed, 104 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 42d73b1..ae6f34e 100644 --- a/package.json +++ b/package.json @@ -2695,6 +2695,21 @@ "markdownDescription": "Specifies whether to enable the preview of _Cloud Patches_, which allow you to easily and securely share code with your teammates or other developers", "scope": "window", "order": 10 + }, + "gitlens.cloudPatches.experimental.layout": { + "type": "string", + "default": "view", + "enum": [ + "editor", + "view" + ], + "enumDescriptions": [ + "Prefer showing Cloud Patches in the editor area", + "Prefer showing Cloud Patches in a view" + ], + "markdownDescription": "Specifies the preferred layout of for _Cloud Patches_", + "scope": "window", + "order": 11 } } }, @@ -5049,6 +5064,11 @@ "category": "GitLens" }, { + "command": "gitlens.showPatchDetailsPage", + "title": "Show Patch Details", + "category": "GitLens" + }, + { "command": "gitlens.createPatch", "title": "Create Patch...", "category": "GitLens" @@ -8582,6 +8602,10 @@ "when": "gitlens:enabled" }, { + "command": "gitlens.showPatchDetailsPage", + "when": "gitlens:enabled && config.gitlens.cloudPatches.enabled" + }, + { "command": "gitlens.createPatch", "when": "false && gitlens:enabled" }, diff --git a/src/config.ts b/src/config.ts index 801ba14..3199a48 100644 --- a/src/config.ts +++ b/src/config.ts @@ -43,6 +43,9 @@ export interface Config { }; readonly cloudPatches: { readonly enabled: boolean; + readonly experimental: { + readonly layout: 'editor' | 'view'; + }; }; readonly codeLens: CodeLensConfig; readonly currentLine: { diff --git a/src/constants.ts b/src/constants.ts index 382ff6b..f476489 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -258,6 +258,7 @@ export const enum Commands { ShowLineCommitInView = 'gitlens.showLineCommitInView', ShowLineHistoryView = 'gitlens.showLineHistoryView', OpenOnlyChangedFiles = 'gitlens.openOnlyChangedFiles', + ShowPatchDetailsPage = 'gitlens.showPatchDetailsPage', ShowQuickBranchHistory = 'gitlens.showQuickBranchHistory', ShowQuickCommit = 'gitlens.showQuickCommitDetails', ShowQuickCommitFile = 'gitlens.showQuickCommitFileDetails', @@ -470,7 +471,7 @@ export type TreeViewTypes = | 'worktrees'; export type TreeViewIds = `gitlens.views.${TreeViewTypes}`; -export type WebviewTypes = 'graph' | 'settings' | 'timeline' | 'welcome' | 'focus'; +export type WebviewTypes = 'focus' | 'graph' | 'patchDetails' | 'settings' | 'timeline' | 'welcome'; export type WebviewIds = `gitlens.${WebviewTypes}`; export type WebviewViewTypes = diff --git a/src/container.ts b/src/container.ts index 3ffb9e9..2dd04b0 100644 --- a/src/container.ts +++ b/src/container.ts @@ -38,7 +38,10 @@ import { } from './plus/webviews/graph/registration'; import { GraphStatusBarController } from './plus/webviews/graph/statusbar'; import type { PatchDetailsWebviewShowingArgs } from './plus/webviews/patchDetails/registration'; -import { registerPatchDetailsWebviewView } from './plus/webviews/patchDetails/registration'; +import { + registerPatchDetailsWebviewPanel, + registerPatchDetailsWebviewView, +} from './plus/webviews/patchDetails/registration'; import type { TimelineWebviewShowingArgs } from './plus/webviews/timeline/registration'; import { registerTimelineWebviewCommands, @@ -260,6 +263,8 @@ export class Container { this._disposables.push((this._repositoriesView = new RepositoriesView(this))); this._disposables.push((this._commitDetailsView = registerCommitDetailsWebviewView(this._webviews))); + const patchDetailsPanels = registerPatchDetailsWebviewPanel(this._webviews); + this._disposables.push(patchDetailsPanels); this._disposables.push((this._patchDetailsView = registerPatchDetailsWebviewView(this._webviews))); this._disposables.push((this._graphDetailsView = registerGraphDetailsWebviewView(this._webviews))); this._disposables.push((this._commitsView = new CommitsView(this))); diff --git a/src/plus/webviews/patchDetails/patchDetailsWebview.ts b/src/plus/webviews/patchDetails/patchDetailsWebview.ts index b6c47c6..9c1856c 100644 --- a/src/plus/webviews/patchDetails/patchDetailsWebview.ts +++ b/src/plus/webviews/patchDetails/patchDetailsWebview.ts @@ -115,6 +115,27 @@ export class PatchDetailsWebviewProvider this._disposable.dispose(); } + canReuseInstance(...args: PatchDetailsWebviewShowingArgs): boolean | undefined { + const [arg] = args; + if (arg?.mode === 'view' && arg.draft != null) { + switch (arg.draft.draftType) { + case 'cloud': + return ( + this._context.draft?.draftType === arg.draft.draftType && + this._context.draft.id === arg.draft.id + ); + + case 'local': + return ( + this._context.draft?.draftType === arg.draft.draftType && + this._context.draft.patch.contents === arg.draft.patch?.contents + ); + } + } + + return false; + } + async onShowing( _loading: boolean, options: WebviewShowOptions, @@ -142,10 +163,12 @@ export class PatchDetailsWebviewProvider } registerCommands(): Disposable[] { - return [ - registerCommand(`${this.host.id}.refresh`, () => this.host.refresh(true)), - registerCommand(`${this.host.id}.close`, () => this.closeView()), - ]; + return this.host.isView() + ? [ + registerCommand(`${this.host.id}.refresh`, () => this.host.refresh(true)), + registerCommand(`${this.host.id}.close`, () => this.closeView()), + ] + : []; } onMessageReceived(e: IpcMessage) { @@ -293,7 +316,10 @@ export class PatchDetailsWebviewProvider private setMode(mode: Mode, silent?: boolean) { this._context.mode = mode; this.setHostTitle(mode); - void setContext('gitlens:views:patchDetails:mode', mode); + void setContext( + 'gitlens:views:patchDetails:mode', + configuration.get('cloudPatches.experimental.layout') === 'editor' ? undefined : mode, + ); if (!silent) { this.updateState(true); } diff --git a/src/plus/webviews/patchDetails/registration.ts b/src/plus/webviews/patchDetails/registration.ts index d6cfaa5..a7c0397 100644 --- a/src/plus/webviews/patchDetails/registration.ts +++ b/src/plus/webviews/patchDetails/registration.ts @@ -1,8 +1,12 @@ +import { ViewColumn } from 'vscode'; +import { Commands } from '../../../constants'; import type { DraftSelectedEvent } from '../../../eventBus'; import type { Repository } from '../../../git/models/repository'; +import { executeCommand } from '../../../system/command'; +import { configuration } from '../../../system/configuration'; import { setContext } from '../../../system/context'; import type { Serialized } from '../../../system/serialize'; -import type { WebviewsController } from '../../../webviews/webviewsController'; +import type { WebviewPanelShowCommandArgs, WebviewsController } from '../../../webviews/webviewsController'; import type { Change, State } from './protocol'; interface CreateDraftFromChanges { @@ -54,6 +58,12 @@ export function registerPatchDetailsWebviewView(controller: WebviewsController) return new PatchDetailsWebviewProvider(container, host); }, async (...args) => { + if (configuration.get('cloudPatches.experimental.layout') === 'editor') { + await setContext('gitlens:views:patchDetails:mode', undefined); + void executeCommand(Commands.ShowPatchDetailsPage, undefined, ...args); + return; + } + const arg = args[0]; if (arg == null) return; @@ -61,3 +71,30 @@ export function registerPatchDetailsWebviewView(controller: WebviewsController) }, ); } + +export function registerPatchDetailsWebviewPanel(controller: WebviewsController) { + return controller.registerWebviewPanel, PatchDetailsWebviewShowingArgs>( + { id: Commands.ShowPatchDetailsPage, options: { preserveInstance: true } }, + { + id: 'gitlens.patchDetails', + fileName: 'patchDetails.html', + iconPath: 'images/gitlens-icon.png', + title: 'Patch', + contextKeyPrefix: `gitlens:webview:patchDetails`, + trackingFeature: 'patchDetailsWebview', + plusFeature: true, + column: ViewColumn.Active, + webviewHostOptions: { + retainContextWhenHidden: false, + enableFindWidget: false, + }, + allowMultipleInstances: true, + }, + async (container, host) => { + const { PatchDetailsWebviewProvider } = await import( + /* webpackChunkName: "patchDetails" */ './patchDetailsWebview' + ); + return new PatchDetailsWebviewProvider(container, host); + }, + ); +}