Skip to content

Commit 591163d

Browse files
committed
feat(mr): comments.
1 parent f69d2c6 commit 591163d

File tree

6 files changed

+198
-20
lines changed

6 files changed

+198
-20
lines changed

src/codingServer.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@ import {
1818
IMRContentResp,
1919
ICreateCommentResp,
2020
IMRStatusResp,
21+
IMRCommentResp,
2122
} from 'src/typings/respResult';
23+
2224
import { PromiseAdapter, promiseFromEvent, parseQuery, parseCloneUrl } from 'src/common/utils';
2325
import { GitService } from 'src/common/gitService';
2426
import { IRepoInfo, ISessionData, TokenType } from 'src/typings/commonTypes';
2527
import { keychain } from 'src/common/keychain';
2628
import Logger from 'src/common/logger';
2729

28-
const AUTH_SERVER = `https://x5p7m.csb.app`;
30+
const AUTH_SERVER = `https://ftxwn9.coding-pages.com`;
2931
const ClientId = `ff768664c96d04235b1cc4af1e3b37a8`;
3032
const ClientSecret = `d29ebb32cab8b5f0a643b5da7dcad8d1469312c7`;
3133

@@ -390,10 +392,10 @@ export class CodingServer {
390392
}
391393
}
392394

393-
public async getMRComments(iid: string) {
395+
public async getMRComments(iid: string | number) {
394396
try {
395397
const { repoApiPrefix } = await this.getApiPrefix();
396-
const result: CodingResponse = await got
398+
const result: IMRCommentResp = await got
397399
.get(`${repoApiPrefix}/merge/${iid}/comments`, {
398400
searchParams: {
399401
access_token: this._session?.accessToken,

src/common/contants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const MRUriScheme = `coding-mr`;

src/extension.ts

+77-15
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import { IFileNode, MRTreeDataProvider } from 'src/tree/mrTree';
77
import { ReleaseTreeDataProvider } from 'src/tree/releaseTree';
88
import { IRepoInfo, IMRWebViewDetail, ISessionData } from 'src/typings/commonTypes';
99
import { GitService } from 'src/common/gitService';
10+
import { ReviewComment, replyNote } from './reviewCommentController';
11+
import { MRUriScheme } from 'src/common/contants';
12+
import { IDiffComment, IMRData } from 'src/typings/respResult';
1013

1114
export async function activate(context: vscode.ExtensionContext) {
1215
await GitService.init();
@@ -42,6 +45,23 @@ export async function activate(context: vscode.ExtensionContext) {
4245
showCollapseAll: true,
4346
});
4447

48+
const commentController = vscode.comments.createCommentController(
49+
'mr-comment',
50+
'Merge request diff comments',
51+
);
52+
context.subscriptions.push(commentController);
53+
54+
commentController.commentingRangeProvider = {
55+
provideCommentingRanges: (document: vscode.TextDocument, token: vscode.CancellationToken) => {
56+
if (document.uri.scheme !== MRUriScheme) {
57+
return;
58+
}
59+
60+
const lineCount = document.lineCount;
61+
return [new vscode.Range(0, 0, lineCount - 1, 0)];
62+
},
63+
};
64+
4565
context.subscriptions.push(vscode.window.registerUriHandler(uriHandler));
4666
context.subscriptions.push(
4767
vscode.commands.registerCommand('codingPlugin.showMROverview', async (mr: IMRWebViewDetail) => {
@@ -184,21 +204,63 @@ export async function activate(context: vscode.ExtensionContext) {
184204
}),
185205
);
186206
context.subscriptions.push(
187-
vscode.commands.registerCommand(`codingPlugin.showDiff`, async (file: IFileNode) => {
188-
const headUri = vscode.Uri.parse(file.path, false).with({
189-
// path: `${file.path}.txt`,
190-
scheme: `mr`,
191-
query: `commit=${file.newSha}&path=${file.path}`,
192-
});
193-
const parentUri = headUri.with({ query: `commit=${file.oldSha}&path=${file.path}` });
194-
await vscode.commands.executeCommand(
195-
`vscode.diff`,
196-
parentUri,
197-
headUri,
198-
`${file.name} (Merge Request)`,
199-
{ preserveFocus: true },
200-
);
201-
}),
207+
vscode.commands.registerCommand(
208+
`codingPlugin.showDiff`,
209+
async (file: IFileNode, mr: IMRData) => {
210+
const headUri = vscode.Uri.parse(file.path, false).with({
211+
scheme: MRUriScheme,
212+
query: `commit=${file.newSha}&path=${file.path}`,
213+
});
214+
const parentUri = headUri.with({ query: `commit=${file.oldSha}&path=${file.path}` });
215+
await vscode.commands.executeCommand(
216+
`vscode.diff`,
217+
parentUri,
218+
headUri,
219+
`${file.name} (Merge Request #${mr.iid})`,
220+
{ preserveFocus: true },
221+
);
222+
223+
const commentResp = await codingSrv.getMRComments(mr.iid);
224+
const comments = (commentResp.data as IDiffComment[][])
225+
.filter((i) => {
226+
const first = i[0];
227+
return !first.outdated && first.path === file.path;
228+
}, [])
229+
.map((i) => {
230+
const root = i[0];
231+
const isRight = root.change_type === 1;
232+
const isLeft = root.change_type === 2;
233+
const both = root.change_type === 3;
234+
235+
const rootLine = root.diffFile.diffLines[root.diffFile.diffLines.length - 1];
236+
const lineNum = isLeft ? rootLine.leftNo : rootLine.rightNo;
237+
const range = new vscode.Range(lineNum, 0, lineNum, 0);
238+
const commentList: vscode.Comment[] = i.map((c) => {
239+
const body = new vscode.MarkdownString(`${c.content}`);
240+
body.isTrusted = true;
241+
const comment: vscode.Comment = {
242+
mode: vscode.CommentMode.Preview,
243+
body: c.content,
244+
author: {
245+
name: `${c.author.name}(${c.author.global_key})`,
246+
iconPath: vscode.Uri.parse(c.author.avatar, false),
247+
},
248+
};
249+
return comment;
250+
});
251+
commentController.createCommentThread(headUri, range, commentList);
252+
});
253+
},
254+
),
255+
);
256+
257+
context.subscriptions.push(
258+
vscode.commands.registerCommand(
259+
`codingPlugin.diff.createComment`,
260+
async (reply: vscode.CommentReply) => {
261+
replyNote(reply);
262+
},
263+
),
202264
);
203265

204266
if (vscode.window.registerWebviewPanelSerializer) {

src/reviewCommentController.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import * as vscode from 'vscode';
2+
3+
let commentId = 1;
4+
5+
export class ReviewComment implements vscode.Comment {
6+
id: number;
7+
label: string | undefined;
8+
constructor(
9+
public body: string | vscode.MarkdownString,
10+
public mode: vscode.CommentMode,
11+
public author: vscode.CommentAuthorInformation,
12+
public parent?: vscode.CommentThread,
13+
public contextValue?: string,
14+
) {
15+
this.id = ++commentId;
16+
}
17+
}
18+
19+
export function replyNote(reply: vscode.CommentReply) {
20+
const thread = reply.thread;
21+
const newComment = new ReviewComment(
22+
reply.text,
23+
vscode.CommentMode.Preview,
24+
{ name: 'vscode' },
25+
thread,
26+
thread.comments.length ? 'canDelete' : undefined,
27+
);
28+
if (thread.contextValue === 'draft') {
29+
newComment.label = 'pending';
30+
}
31+
32+
thread.comments = [...thread.comments, newComment];
33+
}

src/tree/mrTree.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { CodingServer } from 'src/codingServer';
66
import { IRepoInfo, ISessionData, GitChangeType } from 'src/typings/commonTypes';
77
import { IMRDiffStat, IMRData, IMRPathItem } from 'src/typings/respResult';
88
import { getInMemMRContentProvider } from './inMemMRContentProvider';
9+
import { MRUriScheme } from 'src/common/contants';
910

1011
enum MRType {
1112
Open = `open`,
@@ -69,7 +70,7 @@ export class MRTreeDataProvider implements vscode.TreeDataProvider<ListItem<ITre
6970
this._disposables = [];
7071
this._disposables.push(
7172
vscode.workspace.registerTextDocumentContentProvider(
72-
'mr',
73+
MRUriScheme,
7374
getInMemMRContentProvider(context, this._service),
7475
),
7576
);
@@ -233,6 +234,7 @@ export class MRItem extends ListItem<IMRData> {
233234
(f.children || [])?.length > 0
234235
? TreeItemCollapsibleState.Expanded
235236
: TreeItemCollapsibleState.None,
237+
this.value,
236238
),
237239
),
238240
];
@@ -297,6 +299,7 @@ export class FileNode extends ListItem<IFileNode> {
297299
public readonly label: string,
298300
public readonly value: IFileNode,
299301
public readonly collapsibleState: TreeItemCollapsibleState,
302+
public readonly mrData: IMRData,
300303
) {
301304
super(
302305
label,
@@ -306,7 +309,7 @@ export class FileNode extends ListItem<IFileNode> {
306309
? {
307310
command: `codingPlugin.showDiff`,
308311
title: ``,
309-
arguments: [value],
312+
arguments: [value, mrData],
310313
}
311314
: undefined,
312315
FileNode.getFileIcon(value.changeType, collapsibleState),
@@ -333,6 +336,7 @@ export class FileNode extends ListItem<IFileNode> {
333336
(f.children || [])?.length > 0
334337
? TreeItemCollapsibleState.Expanded
335338
: TreeItemCollapsibleState.None,
339+
this.mrData,
336340
),
337341
);
338342
}

src/typings/respResult.ts

+76
Original file line numberDiff line numberDiff line change
@@ -266,3 +266,79 @@ export interface IMRStatus {
266266
export interface IMRStatusResp extends CodingResponse {
267267
data: IMRStatus;
268268
}
269+
270+
export interface IDiffLine {
271+
index: number;
272+
leftNo: number;
273+
rightNo: number;
274+
prefix: string;
275+
text: string;
276+
}
277+
278+
export interface IDiffFile {
279+
linkRef: string;
280+
linkUrl: string;
281+
path: string;
282+
changeType: string;
283+
fileType: string;
284+
type: string;
285+
pathMD5: string;
286+
changeMode: string;
287+
oldMode: string;
288+
newMode: string;
289+
language: string;
290+
insertions: number;
291+
deletions: number;
292+
isChangeInfoValid: boolean;
293+
diffLines: IDiffLine[];
294+
}
295+
296+
export interface IChildComment {
297+
id: number;
298+
noteable_type: string;
299+
noteable_id: number;
300+
content: string;
301+
outdated: boolean;
302+
author: IUserItem;
303+
parentId: number;
304+
created_at: number;
305+
hasResourceReference: boolean;
306+
}
307+
308+
export interface IDiffComment {
309+
id: number;
310+
commitId: string;
311+
noteable_type: string;
312+
noteable_id: number;
313+
line: number;
314+
change_type: number;
315+
position: number;
316+
path: string;
317+
anchor: string;
318+
content: string;
319+
outdated: boolean;
320+
parentId: number;
321+
created_at: number;
322+
hasResourceReference: boolean;
323+
author: IUserItem;
324+
diffFile: IDiffFile;
325+
}
326+
327+
export interface IActivityComment {
328+
id: number;
329+
noteable_type: string;
330+
noteable_id: number;
331+
content: string;
332+
outdated: boolean;
333+
parentId: number;
334+
created_at: number;
335+
hasResourceReference: boolean;
336+
author: IUserItem;
337+
childComments: IChildComment[];
338+
}
339+
340+
export type IMRComment = IDiffComment | IActivityComment;
341+
342+
export interface IMRCommentResp extends CodingResponse {
343+
data: IMRComment[][];
344+
}

0 commit comments

Comments
 (0)