From acef780150fb68b6de86f3d99b982723d175964d Mon Sep 17 00:00:00 2001 From: ccagml Date: Mon, 28 Nov 2022 18:06:13 +0800 Subject: [PATCH 1/3] update --- src/model/Model.ts | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/src/model/Model.ts b/src/model/Model.ts index f549fb3..718699d 100644 --- a/src/model/Model.ts +++ b/src/model/Model.ts @@ -7,7 +7,17 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { ViewColumn, QuickPickItem, MessageItem } from "vscode"; +import { + ViewColumn, + QuickPickItem, + MessageItem, + Comment, + MarkdownString, + CommentMode, + CommentAuthorInformation, + CommentThread, +} from "vscode"; +import { getDayNowM } from "../utils/SystemUtils"; export interface IQuickItemEx extends QuickPickItem { value: T; @@ -259,6 +269,29 @@ export interface ISubmitEvent { accepted: boolean; } +export class RemarkComment implements Comment { + id: number; + label: string | undefined; + constructor( + public body: string | MarkdownString, + public mode: CommentMode, + public author: CommentAuthorInformation, + public parent?: CommentThread, + public contextValue?: string + ) { + this.id = getDayNowM(); + this.label = ""; + } + + getDbString() { + let a = { + name: this.author.name, + id: this.id, + body: this.body, + }; + } +} + export interface IWebViewOption { title: string; viewColumn: ViewColumn; From e83892deaca591ec7470942542530a463433e9c5 Mon Sep 17 00:00:00 2001 From: ccagml Date: Mon, 28 Nov 2022 18:06:20 +0800 Subject: [PATCH 2/3] update --- package.json | 58 +++++---- src/controller/RemarkController.ts | 51 ++++++++ src/controller/TreeViewController.ts | 4 + src/extension.ts | 181 +++++---------------------- src/service/FileButtonService.ts | 19 +++ src/service/RemarkService.ts | 140 +++++++++++++++++++++ src/utils/SystemUtils.ts | 17 +++ 7 files changed, 293 insertions(+), 177 deletions(-) create mode 100644 src/controller/RemarkController.ts create mode 100644 src/service/RemarkService.ts diff --git a/package.json b/package.json index 986c305..0307c4a 100644 --- a/package.json +++ b/package.json @@ -184,41 +184,43 @@ "icon": "$(sort-precedence)" }, { - "command": "mywiki.commentcreateNote", - "title": "Create Note", - "enablement": "!commentIsEmpty" + "command": "lcpr.remarkCreateNote", + "title": "Create Note" }, { - "command": "mywiki.commentreplyNote", - "title": "Reply", - "enablement": "!commentIsEmpty" + "command": "lcpr.remarkAdd", + "title": "测试新加线程?" }, { - "command": "mywiki.commenteditNote", - "title": "Edit", + "command": "lcpr.remarkReplyNote", + "title": "New Note" + }, + { + "command": "lcpr.remarkEditNote", + "title": "Edit Note", "icon": { "dark": "resources/edit_inverse.svg", "light": "resources/edit.svg" } }, { - "command": "mywiki.commentdeleteNoteComment", - "title": "Delete", + "command": "lcpr.remarkDeleteNoteComment", + "title": "Delete Note", "icon": { "dark": "resources/close_inverse.svg", "light": "resources/close.svg" } }, { - "command": "mywiki.commentsaveNote", - "title": "Save" + "command": "lcpr.remarkSaveNote", + "title": "Save Note" }, { - "command": "mywiki.commentcancelsaveNote", - "title": "Cancel" + "command": "lcpr.remarkCancelsaveNote", + "title": "Cancel Note" }, { - "command": "mywiki.commentdispose", + "command": "lcpr.remarkDispose", "title": "Remove All Notes" } ], @@ -246,51 +248,57 @@ "menus": { "commandPalette": [ { - "command": "mywiki.commentcreateNote", + "command": "lcpr.remarkCreateNote", "when": "false" }, { - "command": "mywiki.commentreplyNote", + "command": "lcpr.remarkReplyNote", "when": "false" }, { - "command": "mywiki.commentdeleteNoteComment", + "command": "lcpr.remarkDeleteNoteComment", "when": "false" } ], - "comments/commentThread/title": [], + "comments/commentThread/title": [ + { + "command": "lcpr.remarkAdd", + "group": "inline", + "when": "commentController == comment-sample" + } + ], "comments/commentThread/context": [ { - "command": "mywiki.commentcreateNote", + "command": "lcpr.remarkCreateNote", "group": "inline", "when": "commentController == comment-sample && commentThreadIsEmpty" }, { - "command": "mywiki.commentreplyNote", + "command": "lcpr.remarkReplyNote", "group": "inline", "when": "commentController == comment-sample && !commentThreadIsEmpty" } ], "comments/comment/title": [ { - "command": "mywiki.commenteditNote", + "command": "lcpr.remarkEditNote", "group": "group@1", "when": "commentController == comment-sample" }, { - "command": "mywiki.commentdeleteNoteComment", + "command": "lcpr.remarkDeleteNoteComment", "group": "group@2", "when": "commentController == comment-sample && comment == canDelete" } ], "comments/comment/context": [ { - "command": "mywiki.commentcancelsaveNote", + "command": "lcpr.remarkCancelsaveNote", "group": "inline@1", "when": "commentController == comment-sample" }, { - "command": "mywiki.commentsaveNote", + "command": "lcpr.remarkSaveNote", "group": "inline@2", "when": "commentController == comment-sample" } diff --git a/src/controller/RemarkController.ts b/src/controller/RemarkController.ts new file mode 100644 index 0000000..2906b9a --- /dev/null +++ b/src/controller/RemarkController.ts @@ -0,0 +1,51 @@ +/* + * Filename: /home/cc/vscode-leetcode-problem-rating/src/controller/RemarkController.ts + * Path: /home/cc/vscode-leetcode-problem-rating + * Created Date: Monday, November 28th 2022, 3:29:37 pm + * Author: ccagml + * + * Copyright (c) 2022 ccagml . All rights reserved. + */ + +import { CommentReply, Disposable, TextDocument } from "vscode"; +import { RemarkComment } from "../model/Model"; +import { remarkService } from "../service/RemarkService"; + +// 视图控制器 +class RemarkController implements Disposable { + public dispose(): void {} + + public remarkAdd(a, b, c, d) { + console.log(a); + console.log(b); + console.log(c); + console.log(d); + } + + public remarkCreateNote(reply: CommentReply) { + remarkService.remarkCreateNote(reply); + } + + public remarkReplyNote(reply: CommentReply) { + remarkService.remarkReplyNote(reply); + } + + public remarkDeleteNoteComment(comment: RemarkComment) { + remarkService.remarkDeleteNoteComment(comment); + } + public startRemark(document: TextDocument) { + remarkService.startRemark(document); + } + + public remarkCancelsaveNote(comment: RemarkComment) { + remarkService.remarkCancelsaveNote(comment); + } + public remarkSaveNote(comment: RemarkComment) { + remarkService.remarkSaveNote(comment); + } + public remarkEditNote(comment: RemarkComment) { + remarkService.remarkEditNote(comment); + } +} + +export const remarkController: RemarkController = new RemarkController(); diff --git a/src/controller/TreeViewController.ts b/src/controller/TreeViewController.ts index 58a3971..bc817e5 100644 --- a/src/controller/TreeViewController.ts +++ b/src/controller/TreeViewController.ts @@ -1391,6 +1391,10 @@ class TreeViewController implements Disposable { return this.getNodeById(this.qidToFid.get(qid) || ""); } + public getQidByFid(id: string) { + return this.fidToQid.get(id); + } + public getFavoriteNodes(): NodeModel[] { const res: NodeModel[] = []; for (const node of this.explorerNodeMap.values()) { diff --git a/src/extension.ts b/src/extension.ts index 2a24103..3ef543d 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -7,27 +7,7 @@ * Copyright (c) 2022 ccagml . All rights reserved. */ -import { - ExtensionContext, - window, - commands, - Uri, - // MarkdownString, - // CommentMode, - // CommentAuthorInformation, - // CommentThread, - // Comment, - // CommentReply, - // CommentThreadCollapsibleState, - // CommentReaction, - // CommentController, - // CommentingRangeProvider, - // CommentOptions, - // TextDocument, - // CancellationToken, - // comments, - // Range, -} from "vscode"; +import { ExtensionContext, window, commands, Uri, CommentReply, TextDocument } from "vscode"; import { fileButtonController } from "./controller/FileButtonController"; import { treeViewController } from "./controller/TreeViewController"; import { NodeModel } from "./model/NodeModel"; @@ -44,26 +24,12 @@ import { markdownService } from "./service/MarkdownService"; import { mainContorller } from "./controller/MainController"; import { loginContorller } from "./controller/LoginController"; import { getLeetCodeEndpoint } from "./utils/ConfigUtils"; -import { BricksType, OutPutType } from "./model/Model"; +import { BricksType, OutPutType, RemarkComment } from "./model/Model"; import { bricksDataService } from "./service/BricksDataService"; import { bricksViewController } from "./controller/BricksViewController"; import { statusBarTimeService } from "./service/StatusBarTimeService"; +import { remarkController } from "./controller/RemarkController"; -// let commentId = 1; - -// class NoteComment implements Comment { -// id: number; -// label: string | undefined; -// constructor( -// public body: string | MarkdownString, -// public mode: CommentMode, -// public author: CommentAuthorInformation, -// public parent?: CommentThread, -// public contextValue?: string -// ) { -// this.id = ++commentId; -// } -// } // 激活插件 /** * The main function of the extension. It is called when the extension is activated. @@ -138,7 +104,32 @@ export async function activate(context: ExtensionContext): Promise { ), commands.registerCommand("lcpr.setBricksType6", (node: NodeModel) => bricksViewController.setBricksType(node, BricksType.TYPE_6) - ) + ), + + commands.registerCommand("lcpr.remarkCreateNote", (reply: CommentReply) => { + remarkController.remarkCreateNote(reply); + }), + commands.registerCommand("lcpr.remarkAdd", (a, b, c, d) => { + remarkController.remarkAdd(a, b, c, d); + }), + commands.registerCommand("lcpr.remarkReplyNote", (reply: CommentReply) => { + remarkController.remarkReplyNote(reply); + }), + commands.registerCommand("lcpr.remarkDeleteNoteComment", (comment: RemarkComment) => { + remarkController.remarkDeleteNoteComment(comment); + }), + commands.registerCommand("lcpr.remarkCancelsaveNote", (comment: RemarkComment) => { + remarkController.remarkCancelsaveNote(comment); + }), + commands.registerCommand("lcpr.remarkSaveNote", (comment: RemarkComment) => { + remarkController.remarkSaveNote(comment); + }), + commands.registerCommand("lcpr.remarkEditNote", (comment: RemarkComment) => { + remarkController.remarkEditNote(comment); + }), + commands.registerCommand("lcpr.startRemark", (document: TextDocument) => { + remarkController.startRemark(document); + }) ); // 设置站点 @@ -146,120 +137,6 @@ export async function activate(context: ExtensionContext): Promise { // 获取登录状态 await loginContorller.getLoginStatus(); await bricksViewController.initialize(); - // let aaa; - // // A `CommentController` is able to provide comments for documents. - // const commentController = comments.createCommentController("comment-sample", "Comment API Sample"); - // commentController.commentingRangeProvider = { - // provideCommentingRanges: (document: TextDocument, token: CancellationToken) => { - // let lineCount = document.lineCount; - // aaa = commentController.createCommentThread(document.uri, new Range(5, 0, 10, 0), []); - // aaa.dispose = () => { - // let cac = aaa; - // console.log("ssss"); - // }; - // console.log(aaa); - // return undefined; - // }, - // }; - // let bbb; - // commands.registerCommand("lcpr.previewProblem", (a, b, c) => { - // bbb = commentController.createCommentThread(a, new Range(5, 0, 10, 0), [ - // new NoteComment("ssss", CommentMode.Preview, { name: "vscode" }), - // // new NoteComment("bbbb", CommentMode.Preview, { name: "vscode" }), - // ]); - // }), - // context.subscriptions.push(commentController); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commentcreateNote", (reply: CommentReply) => { - // replyNote(reply); - // }) - // ); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commentreplyNote", (reply: CommentReply) => { - // replyNote(reply); - // }) - // ); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commentdeleteNoteComment", (comment: NoteComment) => { - // let thread = comment.parent; - // if (!thread) { - // return; - // } - - // thread.comments = thread.comments.filter((cmt) => (cmt as NoteComment).id !== comment.id); - - // if (thread.comments.length === 0) { - // thread.dispose(); - // } - // }) - // ); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commentcancelsaveNote", (comment: NoteComment) => { - // if (!comment.parent) { - // return; - // } - - // comment.parent.comments = comment.parent.comments.map((cmt) => { - // if ((cmt as NoteComment).id === comment.id) { - // cmt.mode = CommentMode.Preview; - // } - - // return cmt; - // }); - // }) - // ); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commentsaveNote", (comment: NoteComment) => { - // if (!comment.parent) { - // return; - // } - - // comment.parent.comments = comment.parent.comments.map((cmt) => { - // if ((cmt as NoteComment).id === comment.id) { - // cmt.mode = CommentMode.Preview; - // } - - // return cmt; - // }); - // }) - // ); - - // context.subscriptions.push( - // commands.registerCommand("mywiki.commenteditNote", (comment: NoteComment) => { - // if (!comment.parent) { - // return; - // } - - // comment.parent.comments = comment.parent.comments.map((cmt) => { - // if ((cmt as NoteComment).id === comment.id) { - // cmt.mode = CommentMode.Editing; - // } - - // return cmt; - // }); - // }) - // ); - - // function replyNote(reply: CommentReply) { - // let thread = reply.thread; - // let newComment = new NoteComment( - // reply.text, - // CommentMode.Preview, - // { name: "vscode" }, - // thread, - // thread.comments.length ? "canDelete" : undefined - // ); - // if (thread.contextValue === "draft") { - // newComment.label = "pending"; - // } - - // thread.comments = [...thread.comments, newComment]; - // } } catch (error) { logOutput.appendLine(error.toString()); promptForOpenOutputChannel( diff --git a/src/service/FileButtonService.ts b/src/service/FileButtonService.ts index 4a67c26..7e5edea 100644 --- a/src/service/FileButtonService.ts +++ b/src/service/FileButtonService.ts @@ -137,6 +137,21 @@ export class FileButtonService implements vscode.CodeLensProvider { typescript: "//", }; + public processRemarkButton(codeLensLine, document): vscode.CodeLens[] { + const temp_result: vscode.CodeLens[] = []; + + const range: vscode.Range = new vscode.Range(codeLensLine, 0, codeLensLine, 0); + + temp_result.push( + new vscode.CodeLens(range, { + title: "remark", + command: "lcpr.startRemark", + arguments: [document], + }) + ); + return temp_result; + } + public provideCodeLenses(document: vscode.TextDocument): vscode.ProviderResult { const content: string = document.getText(); const matchResult: RegExpMatchArray | null = content.match(/@lc app=.* id=(.*) lang=.*/); @@ -158,6 +173,10 @@ export class FileButtonService implements vscode.CodeLensProvider { this.processCodeButton(i, document, node).forEach((x) => codeLens.push(x)); } + if (lineContent.indexOf("@lc code=start") >= 0) { + this.processRemarkButton(i, document).forEach((x) => codeLens.push(x)); + } + if (caseFlag && lineContent.indexOf("@lcpr case=end") < 0) { curCase += lineContent.replace(/#/g, "").replace(/\/\//g, "").replace(/--/g, "").replace(/\s+/g, ""); } diff --git a/src/service/RemarkService.ts b/src/service/RemarkService.ts new file mode 100644 index 0000000..3e958f6 --- /dev/null +++ b/src/service/RemarkService.ts @@ -0,0 +1,140 @@ +import { + CommentMode, + CommentThread, + CommentReply, + CommentThreadCollapsibleState, + TextDocument, + CancellationToken, + comments, + Range, + Disposable, +} from "vscode"; +import { treeViewController } from "../controller/TreeViewController"; +import { RemarkComment } from "../model/Model"; +import { getRemakeName } from "../utils/SystemUtils"; + +class RemarkService implements Disposable { + private _remarkComment; + private _qid_map_thread: Map; + + getQidByDocument(document: TextDocument) { + const content: string = document.getText(); + const matchResult: RegExpMatchArray | null = content.match(/@lc app=.* id=(.*) lang=.*/); + let result: Map = new Map(); + if (!matchResult) { + return result; + } + const fid: string | undefined = matchResult[1]; + let qid: string | undefined = treeViewController.getQidByFid(fid); + result["fid"] = fid; + if (qid != undefined) { + result["qid"] = qid.toString(); + } + return result; + } + + constructor() { + this._qid_map_thread = new Map(); + this._remarkComment = comments.createCommentController("comment-sample", "Comment API Sample"); + this._remarkComment.options = { prompt: "新的记录", placeHolder: "开始记录内容" }; + this._remarkComment.commentingRangeProvider = { + provideCommentingRanges: (_: TextDocument, __: CancellationToken) => { + return undefined; + }, + }; + } + + public startRemark(document: TextDocument) { + let docInfo = this.getQidByDocument(document); + if (docInfo["qid"] == undefined) { + return; + } + if (this._qid_map_thread.get(docInfo["qid"]) != undefined) { + // 已经有了 + this._qid_map_thread.get(docInfo["qid"])?.dispose(); + this._qid_map_thread.delete(docInfo["qid"]); + } + for (let i: number = 0; i < document.lineCount; i++) { + const lineContent: string = document.lineAt(i).text; + if (lineContent.indexOf("@lc code=start") >= 0) { + let newRemark = this._remarkComment.createCommentThread(document.uri, new Range(i - 1, 0, i - 1, 0), []); + newRemark.contextValue = `qid:${docInfo["qid"]}`; + newRemark.label = `${docInfo["fid"]}题`; + newRemark.collapsibleState = CommentThreadCollapsibleState.Expanded; + this._qid_map_thread.set(docInfo["qid"], newRemark); + break; + } + } + } + + public remarkCreateNote(reply: CommentReply) { + this.replyNote(reply); + } + + public remarkReplyNote(reply: CommentReply) { + this.replyNote(reply); + } + + public remarkDeleteNoteComment(comment: RemarkComment) { + let thread = comment.parent; + if (!thread) { + return; + } + + thread.comments = thread.comments.filter((cmt) => (cmt as RemarkComment).id !== comment.id); + + // if (thread.comments.length === 0) { + // thread.dispose(); + // } + } + + public remarkCancelsaveNote(comment: RemarkComment) { + if (!comment.parent) { + return; + } + + comment.parent.comments = comment.parent.comments.map((cmt) => { + if ((cmt as RemarkComment).id === comment.id) { + cmt.mode = CommentMode.Preview; + } + + return cmt; + }); + } + public remarkSaveNote(comment: RemarkComment) { + if (!comment.parent) { + return; + } + + comment.parent.comments = comment.parent.comments.map((cmt) => { + if ((cmt as RemarkComment).id === comment.id) { + cmt.mode = CommentMode.Preview; + } + + return cmt; + }); + } + public remarkEditNote(comment: RemarkComment) { + if (!comment.parent) { + return; + } + + comment.parent.comments = comment.parent.comments.map((cmt) => { + if ((cmt as RemarkComment).id === comment.id) { + cmt.mode = CommentMode.Editing; + } + + return cmt; + }); + } + + public replyNote(reply: CommentReply) { + let thread = reply.thread; + let newComment = new RemarkComment(reply.text, CommentMode.Preview, { name: getRemakeName() }, thread, "canDelete"); + thread.comments = [...thread.comments, newComment]; + } + + public dispose(): void {} +} + +export const remarkService: RemarkService = new RemarkService(); diff --git a/src/utils/SystemUtils.ts b/src/utils/SystemUtils.ts index 5458ed9..84bd6ff 100644 --- a/src/utils/SystemUtils.ts +++ b/src/utils/SystemUtils.ts @@ -84,3 +84,20 @@ export function getDayEnd(): number { export function getDayNow(): number { return Math.round(new Date().getTime() / 1000); } + +export function getDayNowM(): number { + return Math.round(new Date().getTime()); +} + +export function getRemakeName(): string { + const date = new Date(); + const year = date.getFullYear(); + const month = date.getMonth() + 1 >= 10 ? date.getMonth() + 1 : `0${date.getMonth() + 1}`; + const day = date.getDate() >= 10 ? date.getDate() : `0${date.getDate()}`; + const hours = date.getHours() >= 10 ? date.getHours() : `0${date.getHours()}`; + const min = date.getMinutes() >= 10 ? date.getMinutes() : `0${date.getMinutes()}`; + const s = date.getSeconds() >= 10 ? date.getSeconds() : `0${date.getSeconds()}`; + + const newDate = `${year}-${month}-${day} ${hours}:${min}:${s}`; + return newDate; +} From 9ce5e50f1a7620898c7fe7112e030580e4cbb62a Mon Sep 17 00:00:00 2001 From: ccagml Date: Tue, 29 Nov 2022 11:40:19 +0800 Subject: [PATCH 3/3] update --- CHANGELOG.md | 4 ++ README.md | 5 ++ package.json | 21 +++----- src/controller/RemarkController.ts | 11 ++-- src/dao/remarkDao.ts | 85 ++++++++++++++++++++++++++++++ src/extension.ts | 4 +- src/model/Model.ts | 27 ++++++---- src/service/RemarkService.ts | 77 ++++++++++++++++++--------- 8 files changed, 179 insertions(+), 55 deletions(-) create mode 100644 src/dao/remarkDao.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 973f5bf..bfe39cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## version 2.4.1 + +- 简易 remark 功能, 用于回忆思考过程? 后续需要用这个数据生成文章 + ## version 2.3.2 - WC320 数据 diff --git a/README.md b/README.md index 3c17c3e..cecb408 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ - [新增区块测试用例](#区块测试用例) - [新增搬砖功能(重复练习?)](#搬砖功能的说明) - [状态栏增加简易计时器](#状态栏增加简易计时器) +- [新增一个 remark 功能](#新增在工作目录存放数据) # 关于本项目 @@ -100,6 +101,10 @@ > > .lcpr_data/ 存数据 > > > > > bricks.json + > > + > > > remark 备注数据 + > > > + > > > > qid 备注 remark 数据 ### bricks.json 存放格式 diff --git a/package.json b/package.json index 0307c4a..d13e0ea 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "vscode-leetcode-problem-rating", "displayName": "LeetCode", "description": "LeetCode 官方插件增强, 代码开源, 增加 LeetCode 题目难度分, 给个star吧, 球球了", - "version": "2.3.2", + "version": "2.4.1", "author": "ccagml", "publisher": "ccagml", "license": "MIT", @@ -188,8 +188,8 @@ "title": "Create Note" }, { - "command": "lcpr.remarkAdd", - "title": "测试新加线程?" + "command": "lcpr.remarkClose", + "title": "关闭?" }, { "command": "lcpr.remarkReplyNote", @@ -249,20 +249,20 @@ "commandPalette": [ { "command": "lcpr.remarkCreateNote", - "when": "false" + "when": "true" }, { "command": "lcpr.remarkReplyNote", - "when": "false" + "when": "true" }, { "command": "lcpr.remarkDeleteNoteComment", - "when": "false" + "when": "true" } ], "comments/commentThread/title": [ { - "command": "lcpr.remarkAdd", + "command": "lcpr.remarkClose", "group": "inline", "when": "commentController == comment-sample" } @@ -292,14 +292,9 @@ } ], "comments/comment/context": [ - { - "command": "lcpr.remarkCancelsaveNote", - "group": "inline@1", - "when": "commentController == comment-sample" - }, { "command": "lcpr.remarkSaveNote", - "group": "inline@2", + "group": "inline@1", "when": "commentController == comment-sample" } ], diff --git a/src/controller/RemarkController.ts b/src/controller/RemarkController.ts index 2906b9a..d47b76d 100644 --- a/src/controller/RemarkController.ts +++ b/src/controller/RemarkController.ts @@ -15,11 +15,8 @@ import { remarkService } from "../service/RemarkService"; class RemarkController implements Disposable { public dispose(): void {} - public remarkAdd(a, b, c, d) { - console.log(a); - console.log(b); - console.log(c); - console.log(d); + public remarkClose(a) { + remarkService.remarkClose(a); } public remarkCreateNote(reply: CommentReply) { @@ -33,8 +30,8 @@ class RemarkController implements Disposable { public remarkDeleteNoteComment(comment: RemarkComment) { remarkService.remarkDeleteNoteComment(comment); } - public startRemark(document: TextDocument) { - remarkService.startRemark(document); + public async startRemark(document: TextDocument) { + await remarkService.startRemark(document); } public remarkCancelsaveNote(comment: RemarkComment) { diff --git a/src/dao/remarkDao.ts b/src/dao/remarkDao.ts new file mode 100644 index 0000000..2984761 --- /dev/null +++ b/src/dao/remarkDao.ts @@ -0,0 +1,85 @@ +// > workspace/ 工作目录 +// > +// > > .lcpr_data/ 存数据 +// > > +// > > > remake/ 备注 +// > > > +// > > > > 题目内部编号.json 根据 qid 备注的信息 +// > > + +import { fetchProblemLanguage, selectWorkspaceFolder } from "../utils/ConfigUtils"; +import { useWsl, toWinPath } from "../utils/SystemUtils"; +import * as path from "path"; +import * as fse from "fs-extra"; + +class RemarkDao { + version = 1; + public async get_remark_dir_path() { + const language: string | undefined = await fetchProblemLanguage(); + if (!language) { + return; + } + const workspaceFolder: string = await selectWorkspaceFolder(false); + if (!workspaceFolder) { + return; + } + let lcpr_data_path: string = path.join(workspaceFolder, ".lcpr_data"); + await fse.ensureDir(lcpr_data_path); + + let remark_dir: string = path.join(lcpr_data_path, "remark"); + await fse.ensureDir(remark_dir); + + remark_dir = useWsl() ? await toWinPath(remark_dir) : remark_dir; + return remark_dir; + } + public async init() { + let lcpr_data_path = await this.get_remark_dir_path(); + if (!lcpr_data_path) { + return; + } + } + + private async getQidPath(qid: string) { + let remark_dir = await this.get_remark_dir_path(); + if (!remark_dir) { + return; + } + if (!qid) { + return; + } + let qid_path: string = path.join(remark_dir, qid); + qid_path = useWsl() ? await toWinPath(qid_path) : qid_path; + return qid_path; + } + + private async _write_data(qid: string, data: object) { + let qid_data_path = await this.getQidPath(qid); + if (!qid_data_path) { + return; + } + return await fse.writeFile(qid_data_path, JSON.stringify(data)); + } + + private async _read_data(qid: string) { + let qid_data_path = await this.getQidPath(qid); + if (!qid_data_path) { + return; + } + + if (!(await fse.pathExists(qid_data_path))) { + return {}; + } + let temp_data = await fse.readFile(qid_data_path, "utf8"); + return JSON.parse(temp_data) || {}; + } + + public async getInfoByQid(qid: string) { + let all_remark = await this._read_data(qid); + return all_remark || {}; + } + public async setInfoByQid(qid: string, info) { + await this._write_data(qid, info); + } +} + +export const remarkDao: RemarkDao = new RemarkDao(); diff --git a/src/extension.ts b/src/extension.ts index 3ef543d..0d543e3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -109,8 +109,8 @@ export async function activate(context: ExtensionContext): Promise { commands.registerCommand("lcpr.remarkCreateNote", (reply: CommentReply) => { remarkController.remarkCreateNote(reply); }), - commands.registerCommand("lcpr.remarkAdd", (a, b, c, d) => { - remarkController.remarkAdd(a, b, c, d); + commands.registerCommand("lcpr.remarkClose", (a) => { + remarkController.remarkClose(a); }), commands.registerCommand("lcpr.remarkReplyNote", (reply: CommentReply) => { remarkController.remarkReplyNote(reply); diff --git a/src/model/Model.ts b/src/model/Model.ts index 718699d..d869157 100644 --- a/src/model/Model.ts +++ b/src/model/Model.ts @@ -17,7 +17,7 @@ import { CommentAuthorInformation, CommentThread, } from "vscode"; -import { getDayNowM } from "../utils/SystemUtils"; +import { getDayNowM, getRemakeName } from "../utils/SystemUtils"; export interface IQuickItemEx extends QuickPickItem { value: T; @@ -272,23 +272,32 @@ export interface ISubmitEvent { export class RemarkComment implements Comment { id: number; label: string | undefined; - constructor( - public body: string | MarkdownString, - public mode: CommentMode, - public author: CommentAuthorInformation, - public parent?: CommentThread, - public contextValue?: string - ) { + mode: CommentMode; + author: CommentAuthorInformation; + contextValue?: string; + + constructor(public body: string | MarkdownString, public parent?: CommentThread) { this.id = getDayNowM(); this.label = ""; + this.contextValue = "canDelete"; + this.mode = CommentMode.Preview; + this.author = { name: getRemakeName() }; } - getDbString() { + getDbData() { let a = { name: this.author.name, id: this.id, body: this.body, }; + return a; + } + + static getObjByDbData(dbData, thread?): RemarkComment { + let obj = new RemarkComment(dbData.body, thread); + obj.id = dbData.id || getDayNowM(); + obj.author = { name: dbData.name }; + return obj; } } diff --git a/src/service/RemarkService.ts b/src/service/RemarkService.ts index 3e958f6..d57e685 100644 --- a/src/service/RemarkService.ts +++ b/src/service/RemarkService.ts @@ -10,8 +10,8 @@ import { Disposable, } from "vscode"; import { treeViewController } from "../controller/TreeViewController"; +import { remarkDao } from "../dao/remarkDao"; import { RemarkComment } from "../model/Model"; -import { getRemakeName } from "../utils/SystemUtils"; class RemarkService implements Disposable { private _remarkComment; @@ -44,7 +44,7 @@ class RemarkService implements Disposable { }; } - public startRemark(document: TextDocument) { + public async startRemark(document: TextDocument) { let docInfo = this.getQidByDocument(document); if (docInfo["qid"] == undefined) { return; @@ -54,12 +54,17 @@ class RemarkService implements Disposable { this._qid_map_thread.get(docInfo["qid"])?.dispose(); this._qid_map_thread.delete(docInfo["qid"]); } + let oldRemark = await this.getOldThreadRemarkByQid(docInfo["qid"]); for (let i: number = 0; i < document.lineCount; i++) { const lineContent: string = document.lineAt(i).text; if (lineContent.indexOf("@lc code=start") >= 0) { - let newRemark = this._remarkComment.createCommentThread(document.uri, new Range(i - 1, 0, i - 1, 0), []); - newRemark.contextValue = `qid:${docInfo["qid"]}`; - newRemark.label = `${docInfo["fid"]}题`; + let newRemark = this._remarkComment.createCommentThread(document.uri, new Range(i - 1, 0, i - 1, 0), oldRemark); + newRemark.comments.forEach((element) => { + element.parent = newRemark; + }); + + newRemark.contextValue = `qid=${docInfo["qid"]}`; + newRemark.label = `${docInfo["fid"]}`; newRemark.collapsibleState = CommentThreadCollapsibleState.Expanded; this._qid_map_thread.set(docInfo["qid"], newRemark); break; @@ -76,16 +81,12 @@ class RemarkService implements Disposable { } public remarkDeleteNoteComment(comment: RemarkComment) { - let thread = comment.parent; - if (!thread) { + if (!comment.parent) { return; } - thread.comments = thread.comments.filter((cmt) => (cmt as RemarkComment).id !== comment.id); - - // if (thread.comments.length === 0) { - // thread.dispose(); - // } + comment.parent.comments = comment.parent.comments.filter((cmt) => (cmt as RemarkComment).id !== comment.id); + this.saveThreadRemark(comment.parent); } public remarkCancelsaveNote(comment: RemarkComment) { @@ -100,19 +101,10 @@ class RemarkService implements Disposable { return cmt; }); + this.saveThreadRemark(comment.parent); } public remarkSaveNote(comment: RemarkComment) { - if (!comment.parent) { - return; - } - - comment.parent.comments = comment.parent.comments.map((cmt) => { - if ((cmt as RemarkComment).id === comment.id) { - cmt.mode = CommentMode.Preview; - } - - return cmt; - }); + this.remarkCancelsaveNote(comment); } public remarkEditNote(comment: RemarkComment) { if (!comment.parent) { @@ -126,12 +118,49 @@ class RemarkService implements Disposable { return cmt; }); + + this.saveThreadRemark(comment.parent); } public replyNote(reply: CommentReply) { let thread = reply.thread; - let newComment = new RemarkComment(reply.text, CommentMode.Preview, { name: getRemakeName() }, thread, "canDelete"); + let newComment = new RemarkComment(reply.text, thread); thread.comments = [...thread.comments, newComment]; + this.saveThreadRemark(thread); + } + + public saveThreadRemark(thread) { + const params: URLSearchParams = new URLSearchParams(thread.contextValue); + let qid = params.get("qid"); + if (!qid) { + return; + } + let data: Array = []; + thread.comments.forEach((element) => { + data.push(element.getDbData()); + }); + let remarkData = {}; + remarkData["data"] = data; + remarkDao.setInfoByQid(qid, remarkData); + } + public async getOldThreadRemarkByQid(qid: string, thread?) { + let remarkData = await remarkDao.getInfoByQid(qid); + let remarkDataBody = remarkData["data"] || []; + let OldRemark: Array = []; + remarkDataBody.forEach((element) => { + OldRemark.push(RemarkComment.getObjByDbData(element, thread)); + }); + return OldRemark; + } + + public remarkClose(thread) { + const params: URLSearchParams = new URLSearchParams(thread.contextValue); + let qid = params.get("qid"); + if (!qid) { + return; + } + + this._qid_map_thread.get(qid)?.dispose(); } public dispose(): void {}