Browse Source

Adds patch repo location when checked

main
Keith Daulton 1 year ago
parent
commit
3e4ca9f2a5
5 changed files with 138 additions and 16 deletions
  1. +44
    -0
      src/plus/webviews/patchDetails/patchDetailsWebview.ts
  2. +17
    -2
      src/plus/webviews/patchDetails/protocol.ts
  3. +42
    -12
      src/webviews/apps/plus/patchDetails/components/gl-draft-details.ts
  4. +7
    -1
      src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts
  5. +28
    -1
      src/webviews/apps/plus/patchDetails/patchDetails.ts

+ 44
- 0
src/plus/webviews/patchDetails/patchDetailsWebview.ts View File

@ -34,6 +34,7 @@ import type {
Change, Change,
CreatePatchParams, CreatePatchParams,
DidExplainParams, DidExplainParams,
DraftPatchCheckedParams,
FileActionParams, FileActionParams,
Mode, Mode,
Preferences, Preferences,
@ -50,8 +51,10 @@ import {
DidChangeCreateNotificationType, DidChangeCreateNotificationType,
DidChangeDraftNotificationType, DidChangeDraftNotificationType,
DidChangeNotificationType, DidChangeNotificationType,
DidChangePatchRepositoryNotificationType,
DidChangePreferencesNotificationType, DidChangePreferencesNotificationType,
DidExplainCommandType, DidExplainCommandType,
DraftPatchCheckedCommandType,
ExplainCommandType, ExplainCommandType,
OpenFileCommandType, OpenFileCommandType,
OpenFileComparePreviousCommandType, OpenFileComparePreviousCommandType,
@ -205,6 +208,9 @@ export class PatchDetailsWebviewProvider
case UpdatePreferencesCommandType.method: case UpdatePreferencesCommandType.method:
onIpc(UpdatePreferencesCommandType, e, params => this.updatePreferences(params)); onIpc(UpdatePreferencesCommandType, e, params => this.updatePreferences(params));
break; break;
case DraftPatchCheckedCommandType.method:
onIpc(DraftPatchCheckedCommandType, e, params => this.onPatchChecked(params));
break;
} }
} }
@ -413,6 +419,43 @@ export class PatchDetailsWebviewProvider
// TODO@eamodio Open the patch contents for the selected repo in an untitled editor // TODO@eamodio Open the patch contents for the selected repo in an untitled editor
} }
private async onPatchChecked(params: DraftPatchCheckedParams) {
if (params.patch.repository.located || params.checked === false) return;
const patch = (this._context.draft as Draft)?.changesets?.[0].patches?.find(
p => p.gkRepositoryId === params.patch.gkRepositoryId,
);
if (patch?.repository == null || isRepository(patch.repository)) return;
const repo = await this.container.repositoryIdentity.getRepository(patch.repository, {
openIfNeeded: true,
prompt: true,
});
if (repo == null) {
void window.showErrorMessage(`Unable to locate repository '${patch.repository.name}'`);
} else {
patch.repository = repo;
}
void this.notifyPatchRepositoryUpdated(patch);
}
private notifyPatchRepositoryUpdated(patch: DraftPatch) {
return this.host.notify(DidChangePatchRepositoryNotificationType, {
patch: serialize({
...patch,
contents: undefined,
commit: undefined,
repository: {
id: patch.gkRepositoryId,
name: patch.repository?.name ?? '',
located: patch.repository != null && isRepository(patch.repository),
},
}),
});
}
private updateCreateCheckedState(params: UpdateCreatePatchRepositoryCheckedStateParams) { private updateCreateCheckedState(params: UpdateCreatePatchRepositoryCheckedStateParams) {
const changeset = this._context.create?.changes.get(params.repoUri); const changeset = this._context.create?.changes.get(params.repoUri);
if (changeset == null) return; if (changeset == null) return;
@ -669,6 +712,7 @@ export class PatchDetailsWebviewProvider
repository: { repository: {
id: p.gkRepositoryId, id: p.gkRepositoryId,
name: p.repository?.name ?? '', name: p.repository?.name ?? '',
located: p.repository != null && isRepository(p.repository),
}, },
})), })),
), ),

+ 17
- 2
src/plus/webviews/patchDetails/protocol.ts View File

@ -13,8 +13,10 @@ export const messageHeadlineSplitterToken = '\x00\n\x00';
export type FileShowOptions = TextDocumentShowOptions; export type FileShowOptions = TextDocumentShowOptions;
type PatchDetails = Serialized<
Omit<DraftPatch, 'commit' | 'contents' | 'repository'> & { repository: { id: GkRepositoryId; name: string } }
export type PatchDetails = Serialized<
Omit<DraftPatch, 'commit' | 'contents' | 'repository'> & {
repository: { id: GkRepositoryId; name: string; located: boolean };
}
>; >;
interface LocalDraftDetails { interface LocalDraftDetails {
@ -183,6 +185,12 @@ export interface OpenInCommitGraphParams {
} }
export const OpenInCommitGraphCommandType = new IpcCommandType<OpenInCommitGraphParams>('patch/openInGraph'); export const OpenInCommitGraphCommandType = new IpcCommandType<OpenInCommitGraphParams>('patch/openInGraph');
export interface DraftPatchCheckedParams {
patch: PatchDetails;
checked: boolean;
}
export const DraftPatchCheckedCommandType = new IpcCommandType<DraftPatchCheckedParams>('patch/checked');
export interface SelectPatchRepoParams { export interface SelectPatchRepoParams {
repoPath: string; repoPath: string;
} }
@ -254,3 +262,10 @@ export type DidExplainParams =
} }
| { error: { message: string } }; | { error: { message: string } };
export const DidExplainCommandType = new IpcNotificationType<DidExplainParams>('patch/didExplain'); export const DidExplainCommandType = new IpcNotificationType<DidExplainParams>('patch/didExplain');
export interface DidChangePatchRepositoryParams {
patch: PatchDetails;
}
export const DidChangePatchRepositoryNotificationType = new IpcNotificationType<DidChangePatchRepositoryParams>(
'patch/draft/didChangeRepository',
);

+ 42
- 12
src/webviews/apps/plus/patchDetails/components/gl-draft-details.ts View File

@ -6,7 +6,12 @@ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { when } from 'lit/directives/when.js'; import { when } from 'lit/directives/when.js';
import type { TextDocumentShowOptions } from 'vscode'; import type { TextDocumentShowOptions } from 'vscode';
import type { DraftPatchFileChange } from '../../../../../gk/models/drafts'; import type { DraftPatchFileChange } from '../../../../../gk/models/drafts';
import type { DraftDetails, FileActionParams, State } from '../../../../../plus/webviews/patchDetails/protocol';
import type {
DraftDetails,
FileActionParams,
PatchDetails,
State,
} from '../../../../../plus/webviews/patchDetails/protocol';
import { makeHierarchical } from '../../../../../system/array'; import { makeHierarchical } from '../../../../../system/array';
import { flatCount } from '../../../../../system/iterable'; import { flatCount } from '../../../../../system/iterable';
import type { import type {
@ -59,6 +64,11 @@ export interface ShowPatchInGraphDetail {
// [key: string]: unknown; // [key: string]: unknown;
} }
export interface PatchCheckedDetail {
patch: PatchDetails;
checked: boolean;
}
@customElement('gl-draft-details') @customElement('gl-draft-details')
export class GlDraftDetails extends GlTreeBase { export class GlDraftDetails extends GlTreeBase {
@property({ type: Object }) @property({ type: Object })
@ -99,6 +109,16 @@ export class GlDraftDetails extends GlTreeBase {
this.selectedPatches = []; this.selectedPatches = [];
} else { } else {
this.selectedPatches = patches.map(p => p.id); this.selectedPatches = patches.map(p => p.id);
for (const patch of patches) {
const index = this.selectedPatches.indexOf(patch.id);
if (patch.repository.located) {
if (index === -1) {
this.selectedPatches.push(patch.id);
}
} else if (index > -1) {
this.selectedPatches.splice(index, 1);
}
}
} }
// } else if (patches?.length === 1) { // } else if (patches?.length === 1) {
// this.selectedPatches = [patches[0].id]; // this.selectedPatches = [patches[0].id];
@ -244,6 +264,7 @@ export class GlDraftDetails extends GlTreeBase {
`; `;
} }
// TODO: make a local state instead of a getter
get treeModel(): TreeModel[] { get treeModel(): TreeModel[] {
if (this.state?.draft?.patches == null) return []; if (this.state?.draft?.patches == null) return [];
@ -262,9 +283,12 @@ export class GlDraftDetails extends GlTreeBase {
} }
// checkable only for multi-repo // checkable only for multi-repo
const options = { checkable: patches.length > 1 };
const isMultiRepo = patches.length > 1;
const models = patches?.map(p => const models = patches?.map(p =>
this.draftPatchToTreeModel(p, isTree, this.state.preferences?.files?.compact, options),
this.draftPatchToTreeModel(p, isTree, this.state.preferences?.files?.compact, {
checkable: isMultiRepo,
checked: this.selectedPatches.includes(p.id),
}),
); );
return models; return models;
} }
@ -530,13 +554,13 @@ export class GlDraftDetails extends GlTreeBase {
this.selectedPatches.splice(selectedIndex, 1); this.selectedPatches.splice(selectedIndex, 1);
} }
// const [repoPath] = e.detail.context;
// const event = new CustomEvent('repo-checked', {
// detail: {
// path: repoPath,
// },
// });
// this.dispatchEvent(event);
const event = new CustomEvent('gl-patch-checked', {
detail: {
patch: patch,
checked: e.detail.checked,
},
});
this.dispatchEvent(event);
} }
override onTreeItemSelected(e: CustomEvent<TreeItemSelectionDetail>) { override onTreeItemSelected(e: CustomEvent<TreeItemSelectionDetail>) {
@ -606,7 +630,12 @@ export class GlDraftDetails extends GlTreeBase {
compact = true, compact = true,
options?: Partial<TreeItemBase>, options?: Partial<TreeItemBase>,
): TreeModel { ): TreeModel {
const model = this.repoToTreeModel(patch.repository.name, patch.gkRepositoryId, options);
const model = this.repoToTreeModel(
patch.repository.name,
patch.gkRepositoryId,
options,
patch.repository.located ? undefined : 'missing',
);
if (!patch.files?.length) return model; if (!patch.files?.length) return model;
@ -677,7 +706,7 @@ export class GlDraftDetails extends GlTreeBase {
declare global { declare global {
interface HTMLElementTagNameMap { interface HTMLElementTagNameMap {
'gl-patch-details': GlDraftDetails;
'gl-draft-details': GlDraftDetails;
} }
interface WindowEventMap { interface WindowEventMap {
@ -688,5 +717,6 @@ declare global {
'gl-patch-file-compare-previous': CustomEvent<FileActionParams>; 'gl-patch-file-compare-previous': CustomEvent<FileActionParams>;
'gl-patch-file-compare-working': CustomEvent<FileActionParams>; 'gl-patch-file-compare-working': CustomEvent<FileActionParams>;
'gl-patch-file-open': CustomEvent<FileActionParams>; 'gl-patch-file-open': CustomEvent<FileActionParams>;
'gl-patch-checked': CustomEvent<PatchCheckedDetail>;
} }
} }

+ 7
- 1
src/webviews/apps/plus/patchDetails/components/gl-tree-base.ts View File

@ -160,7 +160,12 @@ export class GlTreeBase extends GlElement
}; };
} }
protected repoToTreeModel(name: string, path: string, options?: Partial<TreeItemBase>): TreeModel<string[]> {
protected repoToTreeModel(
name: string,
path: string,
options?: Partial<TreeItemBase>,
description?: string,
): TreeModel<string[]> {
return { return {
branch: false, branch: false,
expanded: true, expanded: true,
@ -170,6 +175,7 @@ export class GlTreeBase extends GlElement
checked: true, checked: true,
icon: 'repo', icon: 'repo',
label: name, label: name,
description: description,
context: [path], context: [path],
actions: this.getRepoActions(name, path, options), actions: this.getRepoActions(name, path, options),
...options, ...options,

+ 28
- 1
src/webviews/apps/plus/patchDetails/patchDetails.ts View File

@ -11,8 +11,10 @@ import {
DidChangeCreateNotificationType, DidChangeCreateNotificationType,
DidChangeDraftNotificationType, DidChangeDraftNotificationType,
DidChangeNotificationType, DidChangeNotificationType,
DidChangePatchRepositoryNotificationType,
DidChangePreferencesNotificationType, DidChangePreferencesNotificationType,
DidExplainCommandType, DidExplainCommandType,
DraftPatchCheckedCommandType,
ExplainCommandType, ExplainCommandType,
FileActionsCommandType, FileActionsCommandType,
OpenFileCommandType, OpenFileCommandType,
@ -31,7 +33,7 @@ import type { IpcMessage } from '../../../protocol';
import { ExecuteCommandType, onIpc } from '../../../protocol'; import { ExecuteCommandType, onIpc } from '../../../protocol';
import { App } from '../../shared/appBase'; import { App } from '../../shared/appBase';
import { DOM } from '../../shared/dom'; import { DOM } from '../../shared/dom';
import type { ApplyPatchDetail, GlDraftDetails } from './components/gl-draft-details';
import type { ApplyPatchDetail, GlDraftDetails, PatchCheckedDetail } from './components/gl-draft-details';
import type { import type {
CreatePatchCheckRepositoryEventDetail, CreatePatchCheckRepositoryEventDetail,
CreatePatchEventDetail, CreatePatchEventDetail,
@ -125,6 +127,9 @@ export class PatchDetailsApp extends App> {
'gl-patch-file-open', 'gl-patch-file-open',
e => this.onOpenFile(e.detail), e => this.onOpenFile(e.detail),
), ),
DOM.on<GlDraftDetails, PatchCheckedDetail>('gl-draft-details', 'gl-patch-checked', e =>
this.onPatchChecked(e.detail),
),
]; ];
return disposables; return disposables;
@ -198,11 +203,33 @@ export class PatchDetailsApp extends App> {
}); });
break; break;
case DidChangePatchRepositoryNotificationType.method:
onIpc(DidChangePatchRepositoryNotificationType, msg, params => {
// assertsSerialized<State>(params.state);
const draft = this.state.draft!;
const patches = draft.patches!;
const patchIndex = patches.findIndex(p => p.id === params.patch.id);
patches.splice(patchIndex, 1, params.patch);
this.state = {
...this.state,
draft: draft,
};
this.setState(this.state);
this.attachState(true);
});
break;
default: default:
super.onMessageReceived?.(e); super.onMessageReceived?.(e);
} }
} }
private onPatchChecked(e: PatchCheckedDetail) {
this.sendCommand(DraftPatchCheckedCommandType, e);
}
private onCreateCheckRepo(e: CreatePatchCheckRepositoryEventDetail) { private onCreateCheckRepo(e: CreatePatchCheckRepositoryEventDetail) {
this.sendCommand(UpdateCreatePatchRepositoryCheckedStateCommandType, e); this.sendCommand(UpdateCreatePatchRepositoryCheckedStateCommandType, e);
} }

Loading…
Cancel
Save