Sfoglia il codice sorgente

Added icons to hide and show ref nodes of the graph (#2211)

* Added icons to hide and show ref nodes of the graph

* Added context menu option to hide branches

* Moved "Hide branch" option to the bottom of the menu

* Changes from code review, including

 - Renames some events/methods
 - Fixes context menus
 - Removed unnecessary debounce

* Validate the hidden refs against the real set of refs

* Typed "refType" property  and added to our d.ts file instead of using an string

* Created a "graph only" wrapper for the GitBranchReference rather than adding it to the general model

* Graph exposed event when hiding refs has been modified to accept a list of hidden refs

* Generic context menu when right-click on the overall ref to hide the whole ref.

* Commented hidden refs validation for v13, as it has too much performance impact. Will be solved after we launch v13 as tech debt
main
ericf-axosoft 2 anni fa
committed by GitHub
parent
commit
afd578f24b
Non sono state trovate chiavi note per questa firma nel database ID Chiave GPG: 4AEE18F83AFDEB23
11 ha cambiato i file con 335 aggiunte e 15 eliminazioni
  1. +42
    -0
      package.json
  2. +44
    -7
      src/env/node/git/localGitProvider.ts
  3. +36
    -7
      src/git/models/reference.ts
  4. +8
    -1
      src/git/models/tag.ts
  5. +1
    -0
      src/plus/github/githubGitProvider.ts
  6. +123
    -0
      src/plus/webviews/graph/graphWebview.ts
  7. +22
    -0
      src/plus/webviews/graph/protocol.ts
  8. +9
    -0
      src/storage.ts
  9. +18
    -0
      src/webviews/apps/plus/graph/GraphWrapper.tsx
  10. +14
    -0
      src/webviews/apps/plus/graph/graph.scss
  11. +18
    -0
      src/webviews/apps/plus/graph/graph.tsx

+ 42
- 0
package.json Vedi File

@ -6349,6 +6349,21 @@
"icon": "$(gitlens-switch)"
},
{
"command": "gitlens.graph.hideBranch",
"title": "Hide Branch...",
"category": "GitLens"
},
{
"command": "gitlens.graph.hideTag",
"title": "Hide Tag...",
"category": "GitLens"
},
{
"command": "gitlens.graph.hideGroupedBranch",
"title": "Hide from Graph...",
"category": "GitLens"
},
{
"command": "gitlens.graph.cherryPick",
"title": "Cherry Pick Commit...",
"category": "GitLens"
@ -8372,6 +8387,18 @@
"when": "false"
},
{
"command": "gitlens.graph.hideBranch",
"when": "false"
},
{
"command": "gitlens.graph.hideTag",
"when": "false"
},
{
"command": "gitlens.graph.hideGroupedBranch",
"when": "false"
},
{
"command": "gitlens.graph.cherryPick",
"when": "false"
},
@ -11001,6 +11028,16 @@
"group": "1_gitlens_actions_@10"
},
{
"command": "gitlens.graph.hideBranch",
"when": "webviewItem =~ /gitlens:branch\\b(?!.*?\\b\\+(grouped|current)\\b)/",
"group": "8_gitlens_actions@10"
},
{
"command": "gitlens.graph.hideGroupedBranch",
"when": "webviewItem =~ /gitlens:branch\\b(?!.*?\\b\\+current\\b)/ && webviewItem =~ /gitlens:branch\\+grouped\\b/",
"group": "8_gitlens_actions@11"
},
{
"command": "gitlens.graph.openBranchOnRemote",
"when": "gitlens:hasRemotes && webviewItem =~ /gitlens:branch\\b(?=.*?\\b\\+(tracking|remote)\\b)/",
"group": "2_gitlens_quickopen@1",
@ -11093,6 +11130,11 @@
"group": "1_gitlens_actions@3"
},
{
"command": "gitlens.graph.hideTag",
"when": "webviewItem =~ /gitlens:tag\\b/",
"group": "8_gitlens_actions@10"
},
{
"command": "gitlens.graph.openPullRequestOnRemote",
"when": "webviewItem =~ /gitlens:graph:pullrequest\\b/",
"group": "1_gitlens_actions@1"

+ 44
- 7
src/env/node/git/localGitProvider.ts Vedi File

@ -82,8 +82,8 @@ import { Repository, RepositoryChange, RepositoryChangeComparisonMode } from '..
import type { GitStash } from '../../../git/models/stash';
import type { GitStatusFile } from '../../../git/models/status';
import { GitStatus } from '../../../git/models/status';
import type { GitTag, TagSortOptions } from '../../../git/models/tag';
import { sortTags } from '../../../git/models/tag';
import type { GitTag } from '../../../git/models/tag';
import { getTagId, sortTags, type TagSortOptions } from '../../../git/models/tag';
import type { GitTreeEntry } from '../../../git/models/tree';
import type { GitUser } from '../../../git/models/user';
import { isUserMatch } from '../../../git/models/user';
@ -1788,8 +1788,11 @@ export class LocalGitProvider implements GitProvider, Disposable {
if (tip === 'refs/stash') continue;
if (tip.startsWith('tag: ')) {
const tagName = tip.substring(5);
const tagId = getTagId(repoPath, tagName);
tag = {
name: tip.substring(5),
id: tagId,
name: tagName,
// Not currently used, so don't bother looking it up
annotated: true,
};
@ -1798,6 +1801,7 @@ export class LocalGitProvider implements GitProvider, Disposable {
webviewItemValue: {
type: 'tag',
ref: GitReference.create(tag.name, repoPath, {
id: tagId,
refType: 'tag',
name: tag.name,
}),
@ -1825,24 +1829,28 @@ export class LocalGitProvider implements GitProvider, Disposable {
if (branchName === 'HEAD') continue;
const remoteBranchId = getBranchId(repoPath, true, tip);
const avatarUrl = (
(useAvatars ? remote.provider?.avatarUri : undefined) ??
getRemoteIconUri(this.container, remote, asWebviewUri)
)?.toString(true);
refRemoteHeads.push({
id: remoteBranchId,
name: branchName,
owner: remote.name,
url: remote.url,
avatarUrl: (
(useAvatars ? remote.provider?.avatarUri : undefined) ??
getRemoteIconUri(this.container, remote, asWebviewUri)
)?.toString(true),
avatarUrl: avatarUrl,
context: serializeWebviewItemContext<GraphItemRefContext>({
webviewItem: 'gitlens:branch+remote',
webviewItemValue: {
type: 'branch',
ref: GitReference.create(tip, repoPath, {
id: remoteBranchId,
refType: 'branch',
name: tip,
remote: true,
upstream: { name: remote.name, missing: false },
avatarUrl: avatarUrl,
}),
},
}),
@ -1855,6 +1863,16 @@ export class LocalGitProvider implements GitProvider, Disposable {
branch = branchMap.get(tip);
const branchId = branch?.id ?? getBranchId(repoPath, false, tip);
const groupedRefs: GitReference[] = [];
for (const refRemoteHead of refRemoteHeads) {
if (refRemoteHead.name == tip && refRemoteHead.context) {
const ref = JSON.parse(refRemoteHead.context)?.webviewItemValue?.ref;
if (ref) {
groupedRefs.push(ref);
}
}
}
refHeads.push({
id: branchId,
name: tip,
@ -1866,13 +1884,32 @@ export class LocalGitProvider implements GitProvider, Disposable {
webviewItemValue: {
type: 'branch',
ref: GitReference.create(tip, repoPath, {
id: branchId,
refType: 'branch',
name: tip,
remote: false,
upstream: branch?.upstream,
groupedRefs: groupedRefs,
}),
},
}),
contextGroup: groupedRefs.length > 0
? serializeWebviewItemContext<GraphItemRefContext>({
webviewItem: `gitlens:branch+grouped${head ? '+current' : ''}${
branch?.upstream != null ? '+tracking' : ''
}`,
webviewItemValue: {
type: 'branch',
ref: GitReference.create(tip, repoPath, {
id: branchId,
refType: 'branch',
name: tip,
remote: false,
upstream: branch?.upstream,
groupedRefs: groupedRefs,
}),
},
}) : undefined,
});
}
}

+ 36
- 7
src/git/models/reference.ts Vedi File

@ -101,6 +101,7 @@ export namespace GitRevision {
export interface GitBranchReference {
readonly refType: 'branch';
id?: string;
name: string;
ref: string;
readonly remote: boolean;
@ -108,8 +109,14 @@ export interface GitBranchReference {
repoPath: string;
}
export interface GraphGitBranchReference extends GitBranchReference {
avatarUrl?: string;
groupedRefs?: GitReference[];
}
export interface GitRevisionReference {
readonly refType: 'revision' | 'stash';
id?: undefined;
name: string;
ref: string;
repoPath: string;
@ -120,6 +127,7 @@ export interface GitRevisionReference {
export interface GitStashReference {
readonly refType: 'stash';
id?: undefined;
name: string;
ref: string;
repoPath: string;
@ -130,19 +138,28 @@ export interface GitStashReference {
export interface GitTagReference {
readonly refType: 'tag';
id?: string;
name: string;
ref: string;
repoPath: string;
}
export type GitReference = GitBranchReference | GitRevisionReference | GitStashReference | GitTagReference;
export type GitReference = GitBranchReference | GraphGitBranchReference | GitRevisionReference | GitStashReference | GitTagReference;
export namespace GitReference {
export function create(
ref: string,
repoPath: string,
options: { refType: 'branch'; name: string; remote: boolean; upstream?: { name: string; missing: boolean } },
): GitBranchReference;
options: {
id?: string;
refType: 'branch';
name: string;
remote: boolean;
upstream?: { name: string; missing: boolean };
avatarUrl?: string;
groupedRefs?: GitReference[];
},
): GraphGitBranchReference | GitBranchReference;
export function create(
ref: string,
repoPath: string,
@ -153,24 +170,31 @@ export namespace GitReference {
repoPath: string,
options: { refType: 'stash'; name: string; number: string | undefined; message?: string },
): GitStashReference;
export function create(ref: string, repoPath: string, options: { refType: 'tag'; name: string }): GitTagReference;
export function create(
ref: string,
repoPath: string,
options: { id?: string; refType: 'tag'; name: string },
): GitTagReference;
export function create(
ref: string,
repoPath: string,
options:
| { refType: 'branch'; name: string; remote: boolean }
| { id?: string; refType: 'branch'; name: string; remote: boolean; avatarUrl?: string; groupedRefs?: GitReference[] }
| { refType?: 'revision'; name?: string; message?: string }
| { refType: 'stash'; name: string; number: string | undefined; message?: string }
| { refType: 'tag'; name: string } = { refType: 'revision' },
| { id?: string; refType: 'tag'; name: string } = { refType: 'revision' },
): GitReference {
switch (options.refType) {
case 'branch':
return {
id: options.id,
name: options.name,
ref: ref,
refType: 'branch',
remote: options.remote,
repoPath: repoPath,
avatarUrl: options.avatarUrl,
groupedRefs: options.groupedRefs,
};
case 'stash':
return {
@ -183,6 +207,7 @@ export namespace GitReference {
};
case 'tag':
return {
id: options.id,
name: options.name,
ref: ref,
refType: 'tag',
@ -200,12 +225,15 @@ export namespace GitReference {
}
}
export function fromBranch(branch: GitBranchReference) {
export function fromBranch(branch: GraphGitBranchReference) {
return create(branch.ref, branch.repoPath, {
id: branch.id,
refType: branch.refType,
name: branch.name,
remote: branch.remote,
upstream: branch.upstream,
avatarUrl: branch.avatarUrl,
groupedRefs: branch.groupedRefs,
});
}
@ -228,6 +256,7 @@ export namespace GitReference {
export function fromTag(tag: GitTagReference) {
return create(tag.ref, tag.repoPath, {
id: tag.id,
refType: tag.refType,
name: tag.name,
});

+ 8
- 1
src/git/models/tag.ts Vedi File

@ -10,8 +10,13 @@ export interface TagSortOptions {
orderBy?: TagSorting;
}
export function getTagId(repoPath: string, name: string): string {
return `${repoPath}/tag/${name}`;
}
export class GitTag implements GitTagReference {
readonly refType = 'tag';
readonly id: string;
constructor(
public readonly repoPath: string,
@ -20,7 +25,9 @@ export class GitTag implements GitTagReference {
public readonly message: string,
public readonly date: Date | undefined,
public readonly commitDate: Date | undefined,
) {}
) {
this.id = getTagId(repoPath, name);
}
get formattedDate(): string {
return Container.instance.TagDateFormatting.dateStyle === DateStyle.Absolute

+ 1
- 0
src/plus/github/githubGitProvider.ts Vedi File

@ -1214,6 +1214,7 @@ export class GitHubGitProvider implements GitProvider, Disposable {
if (t.sha !== commit.sha) return undefined;
return {
id: t.id,
name: t.name,
annotated: Boolean(t.message),
context: serializeWebviewItemContext<GraphItemRefContext>({

+ 123
- 0
src/plus/webviews/graph/graphWebview.ts Vedi File

@ -1,3 +1,4 @@
import type { GraphRefType} from '@gitkraken/gitkraken-components';
import type {
ColorTheme,
ConfigurationChangeEvent,
@ -35,6 +36,7 @@ import type { Container } from '../../../container';
import { getContext, onDidChangeContext, setContext } from '../../../context';
import { PlusFeatures } from '../../../features';
import { GitSearchError } from '../../../git/errors';
import { getBranchNameWithoutRemote } from '../../../git/models/branch';
import type { GitCommit } from '../../../git/models/commit';
import { GitContributor } from '../../../git/models/contributor';
import { GitGraphRowType } from '../../../git/models/graph';
@ -86,6 +88,8 @@ import type {
GraphColumnName,
GraphColumnsSettings,
GraphComponentConfig,
GraphHiddenRef,
GraphHiddenRefs,
GraphHostingServiceType,
GraphMissingRefsMetadataType,
GraphPullRequestMetadata,
@ -97,6 +101,7 @@ import type {
SearchParams,
State,
UpdateColumnParams,
UpdateRefsVisibilityParams,
UpdateSelectedRepositoryParams,
UpdateSelectionParams,
} from './protocol';
@ -106,6 +111,7 @@ import {
DidChangeGraphConfigurationNotificationType,
DidChangeNotificationType,
DidChangeRefsMetadataNotificationType,
DidChangeRefsVisibilityNotificationType,
DidChangeRowsNotificationType,
DidChangeSelectionNotificationType,
DidChangeSubscriptionNotificationType,
@ -120,6 +126,7 @@ import {
SearchCommandType,
SearchOpenInViewCommandType,
UpdateColumnCommandType,
UpdateRefsVisibilityCommandType,
UpdateSelectedRepositoryCommandType,
UpdateSelectionCommandType,
} from './protocol';
@ -316,6 +323,10 @@ export class GraphWebview extends WebviewBase {
registerCommand('gitlens.graph.switchToAnotherBranch', this.switchToAnother, this),
registerCommand('gitlens.graph.switchToBranch', this.switchTo, this),
registerCommand('gitlens.graph.hideBranch', this.hideRef, this),
registerCommand('gitlens.graph.hideTag', this.hideRef, this),
registerCommand('gitlens.graph.hideGroupedBranch', this.hideRef, this),
registerCommand('gitlens.graph.cherryPick', this.cherryPick, this),
registerCommand('gitlens.graph.copyRemoteCommitUrl', item => this.openCommitOnRemote(item, true), this),
registerCommand('gitlens.graph.showInDetailsView', this.openInDetailsView, this),
@ -403,6 +414,9 @@ export class GraphWebview extends WebviewBase {
case UpdateColumnCommandType.method:
onIpc(UpdateColumnCommandType, e, params => this.onColumnChanged(params));
break;
case UpdateRefsVisibilityCommandType.method:
onIpc(UpdateRefsVisibilityCommandType, e, params => this.onRefsVisibilityChanged(params));
break;
case UpdateSelectedRepositoryCommandType.method:
onIpc(UpdateSelectedRepositoryCommandType, e, params => this.onSelectedRepositoryChanged(params));
break;
@ -540,6 +554,10 @@ export class GraphWebview extends WebviewBase {
this.updateColumn(e.name, e.config);
}
private onRefsVisibilityChanged(e: UpdateRefsVisibilityParams) {
this.updateHiddenRefs(e.refs, e.visible);
}
@debug()
private async onEnsureRow(e: EnsureRowParams, completionId?: string) {
if (this._graph == null) return;
@ -921,6 +939,19 @@ export class GraphWebview extends WebviewBase {
}
@debug()
private async notifyDidChangeRefsVisibility() {
if (!this.isReady || !this.visible) {
this.addPendingIpcNotification(DidChangeRefsVisibilityNotificationType);
return false;
}
const hiddenRefs = this.getHiddenRefs();
return this.notify(DidChangeRefsVisibilityNotificationType, {
hiddenRefs: await this.getHiddenRefsById(hiddenRefs),
});
}
@debug()
private async notifyDidChangeConfiguration() {
if (!this.isReady || !this.visible) {
this.addPendingIpcNotification(DidChangeGraphConfigurationNotificationType);
@ -1025,6 +1056,7 @@ export class GraphWebview extends WebviewBase {
[DidChangeColumnsNotificationType, this.notifyDidChangeColumns],
[DidChangeGraphConfigurationNotificationType, this.notifyDidChangeConfiguration],
[DidChangeNotificationType, this.notifyDidChangeState],
[DidChangeRefsVisibilityNotificationType, this.notifyDidChangeRefsVisibility],
[DidChangeSelectionNotificationType, this.notifyDidChangeSelection],
[DidChangeSubscriptionNotificationType, this.notifyDidChangeSubscription],
[DidChangeWorkingTreeNotificationType, this.notifyDidChangeWorkingTree],
@ -1088,6 +1120,47 @@ export class GraphWebview extends WebviewBase {
return this.container.storage.getWorkspace('graph:columns');
}
private getHiddenRefs(): Record<string, GraphHiddenRef> | undefined {
return this.container.storage.getWorkspace('graph:hiddenRefs');
}
private async getHiddenRefsById(
hiddenRefs: Record<string, GraphHiddenRef> | undefined
): Promise<GraphHiddenRefs | undefined> {
if (hiddenRefs == null) return undefined;
// This validation has too much performance impact. So we decided to comment those lines
// for v13 and have it as tech debt to solve after we launch.
// See: https://github.com/gitkraken/vscode-gitlens/pull/2211#discussion_r990117432
// if (this.repository == null) {
// this.repository = this.container.git.getBestRepositoryOrFirst();
// if (this.repository == null) return undefined;
// }
// const [hiddenBranches, hiddenTags] = await Promise.all([
// this.repository.getBranches({
// filter: b => !b.current && hiddenRefs[b.id] != undefined,
// }),
// this.repository.getTags({
// filter: t => hiddenRefs[t.id] != undefined,
// }),
// ]);
// const filteredHiddenRefsById: GraphHiddenRefs = {};
// for (const hiddenBranch of hiddenBranches.values) {
// filteredHiddenRefsById[hiddenBranch.id] = hiddenRefs[hiddenBranch.id];
// }
// for (const hiddenTag of hiddenTags.values) {
// filteredHiddenRefsById[hiddenTag.id] = hiddenRefs[hiddenTag.id];
// }
// return filteredHiddenRefsById;
// For v13, we return directly the hidden refs without validating them
return Promise.resolve(hiddenRefs);
}
private getColumnSettings(columns: Record<GraphColumnName, GraphColumnConfig> | undefined): GraphColumnsSettings {
const columnsSettings: GraphColumnsSettings = {
...defaultGraphColumnsSettings,
@ -1224,6 +1297,8 @@ export class GraphWebview extends WebviewBase {
}
const columns = this.getColumns();
const hiddenRefs = this.getHiddenRefs();
const hiddenRefsByIds = await this.getHiddenRefsById(hiddenRefs);
return {
previewBanner: this.previewBanner,
@ -1250,6 +1325,7 @@ export class GraphWebview extends WebviewBase {
context: {
header: this.getColumnHeaderContext(columns),
},
hiddenRefs: hiddenRefsByIds,
nonce: this.cspNonce,
workingTreeStats: getSettledValue(workingStatsResult) ?? { added: 0, deleted: 0, modified: 0 },
};
@ -1262,6 +1338,15 @@ export class GraphWebview extends WebviewBase {
void this.notifyDidChangeColumns();
}
private updateHiddenRefs(refs: GraphHiddenRef[], visible: boolean) {
let hiddenRefs = this.container.storage.getWorkspace('graph:hiddenRefs');
for (const ref of refs) {
hiddenRefs = updateRecordValue(hiddenRefs, ref.id, visible ? undefined : ref);
}
void this.container.storage.storeWorkspace('graph:hiddenRefs', hiddenRefs);
void this.notifyDidChangeRefsVisibility();
}
private resetRefsMetadata(): null | undefined {
this._refsMetadata = getContext(ContextKeys.HasConnectedRemotes) ? undefined : null;
return this._refsMetadata;
@ -1540,6 +1625,44 @@ export class GraphWebview extends WebviewBase {
}
@debug()
private hideRef(item: GraphItemContext) {
if (isGraphItemRefContext(item)) {
const { ref } = item.webviewItemValue;
const groupedRefs: GitReference[] = (ref as any).groupedRefs ?? [];
const refsToHide: GitReference[] = [
...groupedRefs,
ref
];
const graphHiddenRefs: GraphHiddenRef[] = [];
for (const refToHide of refsToHide) {
if (refToHide?.id) {
let isRemoteBranch = false;
let graphRefType: GraphRefType = 'tag';
if (refToHide.refType === 'branch') {
isRemoteBranch = refToHide.remote;
graphRefType = isRemoteBranch ? 'remote' : 'head';
}
graphHiddenRefs.push({
id: refToHide.id,
name: isRemoteBranch ? getBranchNameWithoutRemote(refToHide.name) : refToHide.name,
type: graphRefType,
avatarUrl: (refToHide as any).avatarUrl,
});
}
}
if (graphHiddenRefs.length > 0) {
this.updateHiddenRefs(graphHiddenRefs, false);
}
}
return Promise.resolve();
}
@debug()
private switchToAnother(item: GraphItemContext) {
if (isGraphItemRefContext(item)) {
const { ref } = item.webviewItemValue;

+ 22
- 0
src/plus/webviews/graph/protocol.ts Vedi File

@ -2,8 +2,10 @@ import type {
CssVariables,
GraphColumnSetting,
GraphContexts,
GraphRefOptData,
GraphRow,
GraphZoneType,
HiddenRefsById,
HostingServiceType,
PullRequestMetadata,
RefMetadata,
@ -50,6 +52,7 @@ export interface State {
trialBanner?: boolean;
workingTreeStats?: GraphWorkingTreeStats;
searchResults?: DidSearchParams['results'];
hiddenRefs?: GraphHiddenRefs;
// Props below are computed in the webview (not passed)
activeRow?: string;
@ -105,6 +108,9 @@ export interface GraphColumnConfig {
width?: number;
}
export type GraphHiddenRefs = HiddenRefsById;
export type GraphHiddenRef = GraphRefOptData;
export type GraphColumnName = GraphZoneType;
export type InternalNotificationType = 'didChangeTheme';
@ -160,6 +166,14 @@ export interface UpdateColumnParams {
}
export const UpdateColumnCommandType = new IpcCommandType<UpdateColumnParams>('graph/column/update');
export interface UpdateRefsVisibilityParams {
refs: GraphHiddenRef[];
visible: boolean;
}
export const UpdateRefsVisibilityCommandType = new IpcCommandType<UpdateRefsVisibilityParams>(
'graph/refs/update/visibility',
);
export interface UpdateSelectedRepositoryParams {
path: string;
}
@ -220,6 +234,14 @@ export const DidChangeColumnsNotificationType = new IpcNotificationType
true,
);
export interface DidChangeRefsVisibilityParams {
hiddenRefs?: Record<string, GraphHiddenRef>;
}
export const DidChangeRefsVisibilityNotificationType = new IpcNotificationType<DidChangeRefsVisibilityParams>(
'graph/refs/didChangeVisibility',
true,
);
export interface DidChangeRowsParams {
rows: GraphRow[];
avatars: { [email: string]: string };

+ 9
- 0
src/storage.ts Vedi File

@ -1,3 +1,4 @@
import type { GraphRefType } from '@gitkraken/gitkraken-components';
import type { Disposable, Event, ExtensionContext, SecretStorageChangeEvent } from 'vscode';
import { EventEmitter } from 'vscode';
import type { ViewShowBranchComparison } from './config';
@ -170,6 +171,7 @@ export interface WorkspaceStorage {
dismissed?: Record<string, boolean>;
};
columns?: Record<string, StoredGraphColumn>;
hiddenRefs?: Record<string, StoredGraphHiddenRef>;
};
remote: {
default?: string;
@ -223,6 +225,13 @@ export interface StoredGraphColumn {
width?: number;
}
export interface StoredGraphHiddenRef {
id: string;
name: string;
type: GraphRefType;
avatarUrl?: string;
}
export interface StoredNamedRef {
label?: string;
ref: string;

+ 18
- 0
src/webviews/apps/plus/graph/GraphWrapper.tsx Vedi File

@ -3,6 +3,7 @@ import type {
GraphColumnSetting,
GraphContainerProps,
GraphPlatform,
GraphRefOptData,
GraphRow,
OnFormatCommitDateTime,
} from '@gitkraken/gitkraken-components';
@ -20,6 +21,7 @@ import type {
GraphColumnConfig,
GraphColumnName,
GraphComponentConfig,
GraphHiddenRef,
GraphMissingRefsMetadata,
GraphRepository,
GraphSearchResults,
@ -33,6 +35,7 @@ import {
DidChangeColumnsNotificationType,
DidChangeGraphConfigurationNotificationType,
DidChangeRefsMetadataNotificationType,
DidChangeRefsVisibilityNotificationType,
DidChangeRowsNotificationType,
DidChangeSelectionNotificationType,
DidChangeSubscriptionNotificationType,
@ -57,6 +60,7 @@ export interface GraphWrapperProps {
onMissingAvatars?: (emails: { [email: string]: string }) => void;
onMissingRefsMetadata?: (metadata: GraphMissingRefsMetadata) => void;
onMoreRows?: (id?: string) => void;
onRefsVisibilityChange?: (refs: GraphHiddenRef[], visible: boolean) => void;
onSearch?: (search: SearchQuery | undefined, options?: { limit?: number }) => void;
onSearchPromise?: (
search: SearchQuery,
@ -99,6 +103,8 @@ const createIconElements = (): { [key: string]: ReactElement } => {
'renamed',
'resolved',
'pull-request',
'show',
'hide',
];
const elementLibrary: { [key: string]: ReactElement<any> } = {};
iconList.forEach(iconKey => {
@ -138,6 +144,7 @@ export function GraphWrapper({
onMissingAvatars,
onMissingRefsMetadata,
onMoreRows,
onRefsVisibilityChange,
onSearch,
onSearchPromise,
onSearchOpenInView,
@ -163,6 +170,7 @@ export function GraphWrapper({
const [graphConfig, setGraphConfig] = useState(state.config);
// const [graphDateFormatter, setGraphDateFormatter] = useState(getGraphDateFormatter(config));
const [columns, setColumns] = useState(state.columns);
const [hiddenRefsById, setHiddenRefsById] = useState(state.hiddenRefs);
const [context, setContext] = useState(state.context);
const [pagingHasMore, setPagingHasMore] = useState(state.paging?.hasMore ?? false);
const [isLoading, setIsLoading] = useState(state.loading);
@ -241,6 +249,9 @@ export function GraphWrapper({
case DidChangeSelectionNotificationType:
setSelectedRows(state.selectedRows);
break;
case DidChangeRefsVisibilityNotificationType:
setHiddenRefsById(state.hiddenRefs);
break;
case DidChangeSubscriptionNotificationType:
setIsAccessAllowed(state.allowed ?? false);
setSubscription(state.subscription);
@ -258,6 +269,7 @@ export function GraphWrapper({
setWorkingTreeStats(state.workingTreeStats ?? { added: 0, modified: 0, deleted: 0 });
setGraphConfig(state.config);
setSelectedRows(state.selectedRows);
setHiddenRefsById(state.hiddenRefs);
setContext(state.context);
setAvatars(state.avatars ?? {});
setRefsMetadata(state.refsMetadata);
@ -490,6 +502,10 @@ export function GraphWrapper({
}
};
const handleOnToggleRefsVisibilityClick = (_event: any, refs: GraphRefOptData[], visible: boolean) => {
onRefsVisibilityChange?.(refs, visible);
};
const handleSelectGraphRows = (rows: GraphRow[]) => {
const active = rows[0];
const activeKey = active != null ? `${active.sha}|${active.date}` : undefined;
@ -710,6 +726,7 @@ export function GraphWrapper({
// Just cast the { [id: string]: number } object to { [id: string]: boolean } for performance
highlightedShas={searchResults?.ids as GraphContainerProps['highlightedShas']}
highlightRowsOnRefHover={graphConfig?.highlightRowsOnRefHover}
hiddenRefsById={hiddenRefsById}
showGhostRefsOnRowHover={graphConfig?.showGhostRefsOnRowHover}
showRemoteNamesOnRefs={graphConfig?.showRemoteNamesOnRefs}
isLoadingRows={isLoading}
@ -717,6 +734,7 @@ export function GraphWrapper({
nonce={nonce}
onColumnResized={handleOnColumnResized}
onSelectGraphRows={handleSelectGraphRows}
onToggleRefsVisibilityClick={handleOnToggleRefsVisibilityClick}
onEmailsMissingAvatarUrls={handleMissingAvatars}
onRefsMissingMetadata={handleMissingRefsMetadata}
onShowMoreCommits={handleMoreCommits}

+ 14
- 0
src/webviews/apps/plus/graph/graph.scss Vedi File

@ -435,6 +435,20 @@ a {
content: '\ebb3';
}
}
.icon--hide {
&::before {
// codicon-eye-closed
font-family: codicon;
content: '\eae7';
}
}
.icon--show {
&::before {
// codicon-eye
font-family: codicon;
content: '\ea70';
}
}
.icon--pull-request {
&::before {

+ 18
- 0
src/webviews/apps/plus/graph/graph.tsx Vedi File

@ -9,6 +9,7 @@ import type {
GraphAvatars,
GraphColumnConfig,
GraphColumnName,
GraphHiddenRef,
GraphMissingRefsMetadata,
GraphRepository,
InternalNotificationType,
@ -21,6 +22,7 @@ import {
DidChangeGraphConfigurationNotificationType,
DidChangeNotificationType,
DidChangeRefsMetadataNotificationType,
DidChangeRefsVisibilityNotificationType,
DidChangeRowsNotificationType,
DidChangeSelectionNotificationType,
DidChangeSubscriptionNotificationType,
@ -35,6 +37,7 @@ import {
SearchCommandType,
SearchOpenInViewCommandType,
UpdateColumnCommandType,
UpdateRefsVisibilityCommandType,
UpdateSelectedRepositoryCommandType as UpdateRepositorySelectionCommandType,
UpdateSelectionCommandType,
} from '../../../../plus/webviews/graph/protocol';
@ -84,6 +87,7 @@ export class GraphApp extends App {
(name, settings) => this.onColumnChanged(name, settings),
250,
)}
onRefsVisibilityChange={(refs: GraphHiddenRef[], visible: boolean) => this.onRefsVisibilityChanged(refs, visible)}
onSelectRepository={debounce<GraphApp['onRepositorySelectionChanged']>(
path => this.onRepositorySelectionChanged(path),
250,
@ -146,6 +150,13 @@ export class GraphApp extends App {
});
break;
case DidChangeRefsVisibilityNotificationType.method:
onIpc(DidChangeRefsVisibilityNotificationType, msg, (params, type) => {
this.state.hiddenRefs = params.hiddenRefs;
this.setState(this.state, type);
});
break;
case DidChangeRefsMetadataNotificationType.method:
onIpc(DidChangeRefsMetadataNotificationType, msg, (params, type) => {
this.state.refsMetadata = params.metadata;
@ -370,6 +381,13 @@ export class GraphApp extends App {
});
}
private onRefsVisibilityChanged(refs: GraphHiddenRef[], visible: boolean) {
this.sendCommand(UpdateRefsVisibilityCommandType, {
refs: refs,
visible: visible,
});
}
private onRepositorySelectionChanged(repo: GraphRepository) {
this.sendCommand(UpdateRepositorySelectionCommandType, {
path: repo.path,

Caricamento…
Annulla
Salva