diff --git a/src/plus/webviews/graph/graphWebview.ts b/src/plus/webviews/graph/graphWebview.ts index cd2a7b0..0d16e52 100644 --- a/src/plus/webviews/graph/graphWebview.ts +++ b/src/plus/webviews/graph/graphWebview.ts @@ -165,9 +165,7 @@ export class GraphWebview extends WebviewBase { } protected override async includeBootstrap(): Promise { - return window.withProgress({ location: ProgressLocation.Window, title: 'Loading Commit Graph...' }, async () => - this.getState(), - ); + return this.getState(true); } protected override registerCommands(): Disposable[] { @@ -497,8 +495,8 @@ export class GraphWebview extends WebviewBase { return config; } - private async getState(): Promise { - if (this.container.git.repositoryCount === 0) return { repositories: [] }; + private async getState(deferRows?: boolean): Promise { + if (this.container.git.repositoryCount === 0) return { allowed: true, repositories: [] }; if (this.previewBanner == null || this.trialBanner == null) { const banners = this.container.storage.getWorkspace('graph:banners:dismissed'); @@ -512,7 +510,7 @@ export class GraphWebview extends WebviewBase { if (this.repository == null) { this.repository = this.container.git.getBestRepositoryOrFirst(); - if (this.repository == null) return { repositories: [] }; + if (this.repository == null) return { allowed: true, repositories: [] }; } this._etagRepository = this.repository?.etag; @@ -525,32 +523,48 @@ export class GraphWebview extends WebviewBase { // Check for GitLens+ access const access = await this.getGraphAccess(); - const visibility = access.visibility ?? (await this.container.git.visibility(this.repository.path)); - const data = await this.container.git.getCommitsForGraph( + const dataPromise = this.container.git.getCommitsForGraph( this.repository.path, this._panel!.webview.asWebviewUri.bind(this._panel!.webview), { limit: limit, ref: this._selectedSha ?? 'HEAD' }, ); - this.setGraph(data); - this.setSelectedRows(data.sha); + + let data; + + if (deferRows) { + queueMicrotask(async () => { + const data = await dataPromise; + this.setGraph(data); + this.setSelectedRows(data.sha); + + void this.notifyDidChangeCommits(); + }); + } else { + data = await dataPromise; + this.setGraph(data); + this.setSelectedRows(data.sha); + } return { previewBanner: this.previewBanner, trialBanner: this.trialBanner, repositories: formatRepositories(this.container.git.openRepositories), selectedRepository: this.repository.path, + selectedRepositoryVisibility: visibility, selectedRows: this._selectedRows, - selectedVisibility: visibility, subscription: access.subscription.current, allowed: access.allowed, - avatars: Object.fromEntries(data.avatars), - rows: data.rows, - paging: { - startingCursor: data.paging?.startingCursor, - more: data.paging?.more ?? false, - }, + avatars: data != null ? Object.fromEntries(data.avatars) : undefined, + rows: data?.rows, + paging: + data != null + ? { + startingCursor: data.paging?.startingCursor, + more: data.paging?.more ?? false, + } + : undefined, config: config, nonce: this.cspNonce, }; diff --git a/src/plus/webviews/graph/protocol.ts b/src/plus/webviews/graph/protocol.ts index 391915b..5eb52bc 100644 --- a/src/plus/webviews/graph/protocol.ts +++ b/src/plus/webviews/graph/protocol.ts @@ -8,10 +8,10 @@ import { IpcCommandType, IpcNotificationType } from '../../../webviews/protocol' export interface State { repositories?: GraphRepository[]; selectedRepository?: string; - selectedVisibility?: RepositoryVisibility; + selectedRepositoryVisibility?: RepositoryVisibility; selectedRows?: { [id: string]: true }; subscription?: Subscription; - allowed?: boolean; + allowed: boolean; avatars?: { [email: string]: string }; rows?: GraphRow[]; paging?: GraphPaging; diff --git a/src/webviews/apps/plus/graph/GraphWrapper.tsx b/src/webviews/apps/plus/graph/GraphWrapper.tsx index 29bf4b2..c0b2e02 100644 --- a/src/webviews/apps/plus/graph/GraphWrapper.tsx +++ b/src/webviews/apps/plus/graph/GraphWrapper.tsx @@ -139,7 +139,7 @@ export function GraphWrapper({ selectedRepository, selectedRows, subscription, - selectedVisibility, + selectedRepositoryVisibility, allowed, avatars, config, @@ -164,7 +164,7 @@ export function GraphWrapper({ const [graphSelectedRows, setSelectedRows] = useState(selectedRows); const [graphColSettings, setGraphColSettings] = useState(getGraphColSettingsModel(config)); const [pagingState, setPagingState] = useState(paging); - const [isLoading, setIsLoading] = useState(false); + const [isLoading, setIsLoading] = useState(true); const [styleProps, setStyleProps] = useState(getStyleProps(mixedColumnColors)); // TODO: application shouldn't know about the graph component's header const graphHeaderOffset = 24; @@ -176,7 +176,7 @@ export function GraphWrapper({ // account const [showAccount, setShowAccount] = useState(trialBanner); const [isAllowed, setIsAllowed] = useState(allowed ?? false); - const [isPrivateRepo, setIsPrivateRepo] = useState(selectedVisibility === RepositoryVisibility.Private); + const [isPrivateRepo, setIsPrivateRepo] = useState(selectedRepositoryVisibility === RepositoryVisibility.Private); const [subscriptionSnapshot, setSubscriptionSnapshot] = useState(subscription); // repo selection UI const [repoExpanded, setRepoExpanded] = useState(false); @@ -211,11 +211,11 @@ export function GraphWrapper({ setSelectedRows(state.selectedRows); setGraphColSettings(getGraphColSettingsModel(state.config)); setPagingState(state.paging); - setIsLoading(false); + setIsLoading(state.rows == null); setStyleProps(getStyleProps(state.mixedColumnColors)); setIsAllowed(state.allowed ?? false); setSubscriptionSnapshot(state.subscription); - setIsPrivateRepo(state.selectedVisibility === RepositoryVisibility.Private); + setIsPrivateRepo(state.selectedRepositoryVisibility === RepositoryVisibility.Private); } useEffect(() => {