Browse Source

Switches repo dropdown to picker on Graph

main
Eric Amodio 2 years ago
parent
commit
0b3c31d7db
4 changed files with 67 additions and 81 deletions
  1. +26
    -11
      src/plus/webviews/graph/graphWebview.ts
  2. +3
    -7
      src/plus/webviews/graph/protocol.ts
  3. +30
    -50
      src/webviews/apps/plus/graph/GraphWrapper.tsx
  4. +8
    -13
      src/webviews/apps/plus/graph/graph.tsx

+ 26
- 11
src/plus/webviews/graph/graphWebview.ts View File

@ -30,7 +30,7 @@ import { parseCommandContext } from '../../../commands/base';
import { GitActions } from '../../../commands/gitCommands.actions'; import { GitActions } from '../../../commands/gitCommands.actions';
import type { Config } from '../../../configuration'; import type { Config } from '../../../configuration';
import { configuration } from '../../../configuration'; import { configuration } from '../../../configuration';
import { Commands, ContextKeys, CoreGitCommands } from '../../../constants';
import { Commands, ContextKeys, CoreGitCommands, GlyphChars } from '../../../constants';
import type { Container } from '../../../container'; import type { Container } from '../../../container';
import { getContext, onDidChangeContext } from '../../../context'; import { getContext, onDidChangeContext } from '../../../context';
import { PlusFeatures } from '../../../features'; import { PlusFeatures } from '../../../features';
@ -51,6 +51,7 @@ import type { RepositoryChangeEvent, RepositoryFileSystemChangeEvent } from '../
import { Repository, RepositoryChange, RepositoryChangeComparisonMode } from '../../../git/models/repository'; import { Repository, RepositoryChange, RepositoryChangeComparisonMode } from '../../../git/models/repository';
import type { GitSearch } from '../../../git/search'; import type { GitSearch } from '../../../git/search';
import { getSearchQueryComparisonKey } from '../../../git/search'; import { getSearchQueryComparisonKey } from '../../../git/search';
import { RepositoryPicker } from '../../../quickpicks/repositoryPicker';
import type { StoredGraphFilters, StoredGraphIncludeOnlyRef } from '../../../storage'; import type { StoredGraphFilters, StoredGraphIncludeOnlyRef } from '../../../storage';
import { executeActionCommand, executeCommand, executeCoreGitCommand, registerCommand } from '../../../system/command'; import { executeActionCommand, executeCommand, executeCoreGitCommand, registerCommand } from '../../../system/command';
import { gate } from '../../../system/decorators/gate'; import { gate } from '../../../system/decorators/gate';
@ -104,10 +105,10 @@ import type {
UpdateColumnsParams, UpdateColumnsParams,
UpdateExcludeTypeParams, UpdateExcludeTypeParams,
UpdateRefsVisibilityParams, UpdateRefsVisibilityParams,
UpdateSelectedRepositoryParams,
UpdateSelectionParams, UpdateSelectionParams,
} from './protocol'; } from './protocol';
import { import {
ChooseRepositoryCommandType,
DidChangeAvatarsNotificationType, DidChangeAvatarsNotificationType,
DidChangeColumnsNotificationType, DidChangeColumnsNotificationType,
DidChangeGraphConfigurationNotificationType, DidChangeGraphConfigurationNotificationType,
@ -135,7 +136,6 @@ import {
UpdateExcludeTypeCommandType, UpdateExcludeTypeCommandType,
UpdateIncludeOnlyRefsCommandType, UpdateIncludeOnlyRefsCommandType,
UpdateRefsVisibilityCommandType, UpdateRefsVisibilityCommandType,
UpdateSelectedRepositoryCommandType,
UpdateSelectionCommandType, UpdateSelectionCommandType,
} from './protocol'; } from './protocol';
@ -406,12 +406,18 @@ export class GraphWebview extends WebviewBase {
protected override onMessageReceived(e: IpcMessage) { protected override onMessageReceived(e: IpcMessage) {
switch (e.method) { switch (e.method) {
case ChooseRepositoryCommandType.method:
onIpc(ChooseRepositoryCommandType, e, () => this.onChooseRepository());
break;
case DimMergeCommitsCommandType.method: case DimMergeCommitsCommandType.method:
onIpc(DimMergeCommitsCommandType, e, params => this.dimMergeCommits(params)); onIpc(DimMergeCommitsCommandType, e, params => this.dimMergeCommits(params));
break; break;
case DismissBannerCommandType.method: case DismissBannerCommandType.method:
onIpc(DismissBannerCommandType, e, params => this.dismissBanner(params)); onIpc(DismissBannerCommandType, e, params => this.dismissBanner(params));
break; break;
case DoubleClickedRefCommandType.method:
onIpc(DoubleClickedRefCommandType, e, params => this.onDoubleClickRef(params));
break;
case EnsureRowCommandType.method: case EnsureRowCommandType.method:
onIpc(EnsureRowCommandType, e, params => this.onEnsureRow(params, e.completionId)); onIpc(EnsureRowCommandType, e, params => this.onEnsureRow(params, e.completionId));
break; break;
@ -436,12 +442,6 @@ export class GraphWebview extends WebviewBase {
case UpdateRefsVisibilityCommandType.method: case UpdateRefsVisibilityCommandType.method:
onIpc(UpdateRefsVisibilityCommandType, e, params => this.onRefsVisibilityChanged(params)); onIpc(UpdateRefsVisibilityCommandType, e, params => this.onRefsVisibilityChanged(params));
break; break;
case DoubleClickedRefCommandType.method:
onIpc(DoubleClickedRefCommandType, e, params => this.onDoubleClickRef(params));
break;
case UpdateSelectedRepositoryCommandType.method:
onIpc(UpdateSelectedRepositoryCommandType, e, params => this.onSelectedRepositoryChanged(params));
break;
case UpdateSelectionCommandType.method: case UpdateSelectionCommandType.method:
onIpc(UpdateSelectionCommandType, e, this.onSelectionChanged.bind(this)); onIpc(UpdateSelectionCommandType, e, this.onSelectionChanged.bind(this));
break; break;
@ -896,8 +896,23 @@ export class GraphWebview extends WebviewBase {
}); });
} }
private onSelectedRepositoryChanged(e: UpdateSelectedRepositoryParams) {
this.repository = this.container.git.getRepository(e.path);
private async onChooseRepository() {
// Ensure that the current repository is always last
const repositories = this.container.git.openRepositories.sort(
(a, b) =>
(a === this.repository ? 1 : -1) - (b === this.repository ? 1 : -1) ||
(a.starred ? -1 : 1) - (b.starred ? -1 : 1) ||
a.index - b.index,
);
const pick = await RepositoryPicker.show(
`Switch Repository ${GlyphChars.Dot} ${this.repository?.name}`,
'Choose a repository to switch to',
repositories,
);
if (pick == null) return;
this.repository = pick.item;
} }
private _fireSelectionChangedDebounced: Deferrable<GraphWebview['fireSelectionChanged']> | undefined = undefined; private _fireSelectionChangedDebounced: Deferrable<GraphWebview['fireSelectionChanged']> | undefined = undefined;

+ 3
- 7
src/plus/webviews/graph/protocol.ts View File

@ -141,6 +141,9 @@ export interface UpdateStateCallback {
} }
// Commands // Commands
export const ChooseRepositoryCommandType = new IpcCommandType<undefined>('graph/chooseRepository');
export interface DimMergeCommitsParams { export interface DimMergeCommitsParams {
dim: boolean; dim: boolean;
} }
@ -219,13 +222,6 @@ export const UpdateIncludeOnlyRefsCommandType = new IpcCommandType
'graph/fitlers/update/includeOnlyRefs', 'graph/fitlers/update/includeOnlyRefs',
); );
export interface UpdateSelectedRepositoryParams {
path: string;
}
export const UpdateSelectedRepositoryCommandType = new IpcCommandType<UpdateSelectedRepositoryParams>(
'graph/selectedRepository/update',
);
export interface UpdateSelectionParams { export interface UpdateSelectionParams {
selection: { id: string; type: GitGraphRowType }[]; selection: { id: string; type: GitGraphRowType }[];
} }

+ 30
- 50
src/webviews/apps/plus/graph/GraphWrapper.tsx View File

@ -65,7 +65,7 @@ export interface GraphWrapperProps {
nonce?: string; nonce?: string;
state: State; state: State;
subscriber: (callback: UpdateStateCallback) => () => void; subscriber: (callback: UpdateStateCallback) => () => void;
onSelectRepository?: (repository: GraphRepository) => void;
onChooseRepository?: () => void;
onColumnsChange?: (colsSettings: GraphColumnsConfig) => void; onColumnsChange?: (colsSettings: GraphColumnsConfig) => void;
onDimMergeCommits?: (dim: boolean) => void; onDimMergeCommits?: (dim: boolean) => void;
onDoubleClickRef?: (ref: GraphRef) => void; onDoubleClickRef?: (ref: GraphRef) => void;
@ -140,7 +140,7 @@ export function GraphWrapper({
subscriber, subscriber,
nonce, nonce,
state, state,
onSelectRepository,
onChooseRepository,
onColumnsChange, onColumnsChange,
onDimMergeCommits, onDimMergeCommits,
onDoubleClickRef, onDoubleClickRef,
@ -485,11 +485,8 @@ export function GraphWrapper({
return undefined; return undefined;
}; };
const handleSelectRepository = (item: GraphRepository) => {
if (item != null && item !== repo) {
setIsLoading(true);
onSelectRepository?.(item);
}
const handleChooseRepository = () => {
onChooseRepository?.();
}; };
const handleExcludeTypeChange = (e: Event | FormEvent<HTMLElement>) => { const handleExcludeTypeChange = (e: Event | FormEvent<HTMLElement>) => {
@ -779,53 +776,32 @@ export function GraphWrapper({
<header className="titlebar graph-app__header"> <header className="titlebar graph-app__header">
<div className="titlebar__row titlebar__row--wrap"> <div className="titlebar__row titlebar__row--wrap">
<div className="titlebar__group titlebar__group--fixed"> <div className="titlebar__group titlebar__group--fixed">
{repos.length < 2 ? (
<button type="button" className="action-button" disabled>
{repo?.formattedName ?? 'none selected'}
</button>
) : (
<PopMenu>
<button
type="button"
className="action-button"
slot="trigger"
disabled={repos.length < 2}
>
{repo?.formattedName ?? 'none selected'}
{repos.length > 1 && (
<span
className="codicon codicon-chevron-down action-button__more"
aria-hidden="true"
></span>
)}
</button>
<MenuList role="listbox" slot="content">
{repos.length > 0 &&
repos.map((item, index) => (
<MenuItem
aria-selected={item.path === repo?.path}
onClick={() => handleSelectRepository(item)}
disabled={item.path === repo?.path}
key={`repo-actioncombo-item-${index}`}
>
<span
className={`${
item.path === repo?.path ? 'codicon codicon-check ' : ''
}actioncombo__icon`}
aria-label="Checked"
></span>
{item.formattedName}
</MenuItem>
))}
</MenuList>
</PopMenu>
)}
<button
type="button"
className="action-button"
slot="trigger"
title="Switch to Another Repository..."
disabled={repos.length < 2}
onClick={() => handleChooseRepository()}
>
{repo?.formattedName ?? 'none selected'}
{repos.length > 1 && (
<span
className="codicon codicon-chevron-down action-button__more"
aria-hidden="true"
></span>
)}
</button>
{repo && ( {repo && (
<> <>
<span> <span>
<span className="codicon codicon-chevron-right"></span> <span className="codicon codicon-chevron-right"></span>
</span> </span>
<a href="command:gitlens.graph.switchToAnotherBranch" className="action-button">
<a
href="command:gitlens.graph.switchToAnotherBranch"
className="action-button"
title="Switch to Another Branch..."
>
{branchName} {branchName}
<span <span
className="codicon codicon-chevron-down action-button__more" className="codicon codicon-chevron-down action-button__more"
@ -835,7 +811,11 @@ export function GraphWrapper({
<span> <span>
<span className="codicon codicon-chevron-right"></span> <span className="codicon codicon-chevron-right"></span>
</span> </span>
<a href="command:gitlens.graph.fetch" className="action-button">
<a
href="command:gitlens.graph.fetch"
className="action-button"
title="Fetch Repository"
>
<span className="codicon codicon-sync action-button__icon"></span> Fetch{' '} <span className="codicon codicon-sync action-button__icon"></span> Fetch{' '}
{lastFetched && <small>(Last fetched {fromNow(new Date(lastFetched))})</small>} {lastFetched && <small>(Last fetched {fromNow(new Date(lastFetched))})</small>}
</a> </a>

+ 8
- 13
src/webviews/apps/plus/graph/graph.tsx View File

@ -11,11 +11,12 @@ import type {
GraphExcludedRef, GraphExcludedRef,
GraphExcludeTypes, GraphExcludeTypes,
GraphMissingRefsMetadata, GraphMissingRefsMetadata,
GraphRepository,
InternalNotificationType, InternalNotificationType,
State, State,
UpdateStateCallback} from '../../../../plus/webviews/graph/protocol';
UpdateStateCallback,
} from '../../../../plus/webviews/graph/protocol';
import { import {
ChooseRepositoryCommandType,
DidChangeAvatarsNotificationType, DidChangeAvatarsNotificationType,
DidChangeColumnsNotificationType, DidChangeColumnsNotificationType,
DidChangeGraphConfigurationNotificationType, DidChangeGraphConfigurationNotificationType,
@ -43,7 +44,6 @@ import {
UpdateExcludeTypeCommandType, UpdateExcludeTypeCommandType,
UpdateIncludeOnlyRefsCommandType, UpdateIncludeOnlyRefsCommandType,
UpdateRefsVisibilityCommandType, UpdateRefsVisibilityCommandType,
UpdateSelectedRepositoryCommandType as UpdateRepositorySelectionCommandType,
UpdateSelectionCommandType, UpdateSelectionCommandType,
} from '../../../../plus/webviews/graph/protocol'; } from '../../../../plus/webviews/graph/protocol';
import { debounce } from '../../../../system/function'; import { debounce } from '../../../../system/function';
@ -96,10 +96,7 @@ export class GraphApp extends App {
onRefsVisibilityChange={(refs: GraphExcludedRef[], visible: boolean) => onRefsVisibilityChange={(refs: GraphExcludedRef[], visible: boolean) =>
this.onRefsVisibilityChanged(refs, visible) this.onRefsVisibilityChanged(refs, visible)
} }
onSelectRepository={debounce<GraphApp['onRepositorySelectionChanged']>(
path => this.onRepositorySelectionChanged(path),
250,
)}
onChooseRepository={debounce<GraphApp['onChooseRepository']>(() => this.onChooseRepository(), 250)}
onDoubleClickRef={ref => this.onDoubleClickRef(ref)} onDoubleClickRef={ref => this.onDoubleClickRef(ref)}
onMissingAvatars={(...params) => this.onGetMissingAvatars(...params)} onMissingAvatars={(...params) => this.onGetMissingAvatars(...params)}
onMissingRefsMetadata={(...params) => this.onGetMissingRefsMetadata(...params)} onMissingRefsMetadata={(...params) => this.onGetMissingRefsMetadata(...params)}
@ -414,6 +411,10 @@ export class GraphApp extends App {
}); });
} }
private onChooseRepository() {
this.sendCommand(ChooseRepositoryCommandType, undefined);
}
private onDimMergeCommits(dim: boolean) { private onDimMergeCommits(dim: boolean) {
this.sendCommand(DimMergeCommitsCommandType, { this.sendCommand(DimMergeCommitsCommandType, {
dim: dim, dim: dim,
@ -426,12 +427,6 @@ export class GraphApp extends App {
}); });
} }
private onRepositorySelectionChanged(repo: GraphRepository) {
this.sendCommand(UpdateRepositorySelectionCommandType, {
path: repo.path,
});
}
private onGetMissingAvatars(emails: GraphAvatars) { private onGetMissingAvatars(emails: GraphAvatars) {
this.sendCommand(GetMissingAvatarsCommandType, { emails: emails }); this.sendCommand(GetMissingAvatarsCommandType, { emails: emails });
} }

Loading…
Cancel
Save