diff --git a/src/@types/vscode.proposed.chatParticipantAdditions.d.ts b/src/@types/vscode.proposed.chatParticipantAdditions.d.ts index 369d340afe..c1f4e12c15 100644 --- a/src/@types/vscode.proposed.chatParticipantAdditions.d.ts +++ b/src/@types/vscode.proposed.chatParticipantAdditions.d.ts @@ -258,6 +258,13 @@ declare module 'vscode' { readonly tools: Map; } + export namespace lm { + /** + * Fired when the set of tools on a chat request changes. + */ + export const onDidChangeChatRequestTools: Event; + } + // TODO@API fit this into the stream export interface ChatUsedContext { documents: ChatDocumentContext[]; diff --git a/src/github/pullRequestOverview.ts b/src/github/pullRequestOverview.ts index 903501d8f9..6f5a1d4edb 100644 --- a/src/github/pullRequestOverview.ts +++ b/src/github/pullRequestOverview.ts @@ -387,6 +387,8 @@ export class PullRequestOverviewPanel extends IssueOverviewPanel) { + try { + const result = await this._item.deleteReview(); + await this._replyMessage(message, result); + } catch (e) { + Logger.error(formatError(e), PullRequestOverviewPanel.ID); + vscode.window.showErrorMessage(vscode.l10n.t('Deleting review failed. {0}', formatError(e))); + this._throwError(message, `${formatError(e)}`); + } + } + override dispose() { super.dispose(); disposeAll(this._prListeners); diff --git a/webviews/common/context.tsx b/webviews/common/context.tsx index 6b823be303..e3ee7d5312 100644 --- a/webviews/common/context.tsx +++ b/webviews/common/context.tsx @@ -145,6 +145,25 @@ export class PRContext { public submit = (body: string) => this.submitReviewCommand('pr.submit', body); + public deleteReview = async () => { + try { + const result: { deletedReviewId: number; deletedReviewComments: IComment[] } = await this.postMessage({ command: 'pr.delete-review' }); + // Update the PR state to reflect the deleted review + const state = this.pr; + state.busy = false; + state.pendingCommentText = ''; + state.pendingCommentDrafts = {}; + // Remove the deleted review from events + state.events = state.events.filter(event => + !(event.event === EventType.Reviewed && event.id === result.deletedReviewId) + ); + this.updatePR(state); + return result; + } catch (error) { + return this.updatePR({ busy: false }); + } + }; + public close = async (body?: string) => { try { const result: CloseResult = await this.postMessage({ command: 'pr.close', args: body }); diff --git a/webviews/components/timeline.tsx b/webviews/components/timeline.tsx index 9f88810aa8..9cd92e481d 100644 --- a/webviews/components/timeline.tsx +++ b/webviews/components/timeline.tsx @@ -267,7 +267,7 @@ function CommentThread({ thread, event }: { thread: IComment[]; event: ReviewEve } function AddReviewSummaryComment() { - const { requestChanges, approve, submit, pr } = useContext(PullRequestContext); + const { requestChanges, approve, submit, deleteReview, pr } = useContext(PullRequestContext); const { isAuthor } = pr; const comment = useRef(); const [isBusy, setBusy] = useState(false); @@ -289,6 +289,13 @@ function AddReviewSummaryComment() { setBusy(false); } + async function cancelReview(event: React.MouseEvent): Promise { + event.preventDefault(); + setBusy(true); + await deleteReview(); + setBusy(false); + } + const onKeyDown = (event: React.KeyboardEvent) => { if ((event.ctrlKey || event.metaKey) && event.key === 'Enter') { submitAction(event, ReviewType.Comment); @@ -304,6 +311,14 @@ function AddReviewSummaryComment() { onKeyDown={onKeyDown} >
+ {isAuthor ? null : (