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,
CreatePatchParams,
DidExplainParams,
DraftPatchCheckedParams,
FileActionParams,
Mode,
Preferences,
@ -50,8 +51,10 @@ import {
DidChangeCreateNotificationType,
DidChangeDraftNotificationType,
DidChangeNotificationType,
DidChangePatchRepositoryNotificationType,
DidChangePreferencesNotificationType,
DidExplainCommandType,
DraftPatchCheckedCommandType,
ExplainCommandType,
OpenFileCommandType,
OpenFileComparePreviousCommandType,
@ -205,6 +208,9 @@ export class PatchDetailsWebviewProvider
case UpdatePreferencesCommandType.method:
onIpc(UpdatePreferencesCommandType, e, params => this.updatePreferences(params));
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
}
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) {
const changeset = this._context.create?.changes.get(params.repoUri);
if (changeset == null) return;
@ -669,6 +712,7 @@ export class PatchDetailsWebviewProvider
repository: {
id: p.gkRepositoryId,
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;
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 {
@ -183,6 +185,12 @@ export interface OpenInCommitGraphParams {
}
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 {
repoPath: string;
}
@ -254,3 +262,10 @@ export type DidExplainParams =
}
| { error: { message: string } };
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 type { TextDocumentShowOptions } from 'vscode';
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 { flatCount } from '../../../../../system/iterable';
import type {
@ -59,6 +64,11 @@ export interface ShowPatchInGraphDetail {
// [key: string]: unknown;
}
export interface PatchCheckedDetail {
patch: PatchDetails;
checked: boolean;
}
@customElement('gl-draft-details')
export class GlDraftDetails extends GlTreeBase {
@property({ type: Object })
@ -99,6 +109,16 @@ export class GlDraftDetails extends GlTreeBase {
this.selectedPatches = [];
} else {
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) {
// 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[] {
if (this.state?.draft?.patches == null) return [];
@ -262,9 +283,12 @@ export class GlDraftDetails extends GlTreeBase {
}
// checkable only for multi-repo
const options = { checkable: patches.length > 1 };
const isMultiRepo = patches.length > 1;
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;
}
@ -530,13 +554,13 @@ export class GlDraftDetails extends GlTreeBase {
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>) {
@ -606,7 +630,12 @@ export class GlDraftDetails extends GlTreeBase {
compact = true,
options?: Partial<TreeItemBase>,
): 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;
@ -677,7 +706,7 @@ export class GlDraftDetails extends GlTreeBase {
declare global {
interface HTMLElementTagNameMap {
'gl-patch-details': GlDraftDetails;
'gl-draft-details': GlDraftDetails;
}
interface WindowEventMap {
@ -688,5 +717,6 @@ declare global {
'gl-patch-file-compare-previous': CustomEvent<FileActionParams>;
'gl-patch-file-compare-working': 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 {
branch: false,
expanded: true,
@ -170,6 +175,7 @@ export class GlTreeBase extends GlElement
checked: true,
icon: 'repo',
label: name,
description: description,
context: [path],
actions: this.getRepoActions(name, path, options),
...options,

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

@ -11,8 +11,10 @@ import {
DidChangeCreateNotificationType,
DidChangeDraftNotificationType,
DidChangeNotificationType,
DidChangePatchRepositoryNotificationType,
DidChangePreferencesNotificationType,
DidExplainCommandType,
DraftPatchCheckedCommandType,
ExplainCommandType,
FileActionsCommandType,
OpenFileCommandType,
@ -31,7 +33,7 @@ import type { IpcMessage } from '../../../protocol';
import { ExecuteCommandType, onIpc } from '../../../protocol';
import { App } from '../../shared/appBase';
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 {
CreatePatchCheckRepositoryEventDetail,
CreatePatchEventDetail,
@ -125,6 +127,9 @@ export class PatchDetailsApp extends App> {
'gl-patch-file-open',
e => this.onOpenFile(e.detail),
),
DOM.on<GlDraftDetails, PatchCheckedDetail>('gl-draft-details', 'gl-patch-checked', e =>
this.onPatchChecked(e.detail),
),
];
return disposables;
@ -198,11 +203,33 @@ export class PatchDetailsApp extends App> {
});
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:
super.onMessageReceived?.(e);
}
}
private onPatchChecked(e: PatchCheckedDetail) {
this.sendCommand(DraftPatchCheckedCommandType, e);
}
private onCreateCheckRepo(e: CreatePatchCheckRepositoryEventDetail) {
this.sendCommand(UpdateCreatePatchRepositoryCheckedStateCommandType, e);
}

Loading…
Cancel
Save