Skip to content

Commit 04300b1

Browse files
committed
feat(view): add my favorites view
1 parent 6131212 commit 04300b1

19 files changed

+334
-15
lines changed

docs/walkthroughs/Overview.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
3. 快速提交、测试你的代码
1010
4. 在源文件中嵌入自定义测试样例并提交测试
1111
5. 快速搜索公共题库中的习题
12-
6. 内置常用的 C++、Java 代码模板
12+
6. 以 Markdown 的格式记录笔记
13+
7. 收藏题目在本地
14+
8. 内置常用的 C++、Java 代码模板
1315

1416
使用 Pintia Extension 帮助你高效地在 VS Code 中完成拼题 A 的编程练习。
1517

docs/walkthroughs/Overview_en-US.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
3. Submit and test your code quickly
88
4. Create custom test samples in the source file and submit them quickly
99
5. Search for public problems quickly
10-
6. Built-in common C++, Java code templates
10+
6. Take Notes in Markdown
11+
7. Add your favorite problems
12+
8. Built-in common C++, Java code templates
1113

1214
Use the Pintia Extension to help you efficiently complete programming exercises in Pintia (PTA) in VS Code.
1315

package.json

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@
2727
"Other",
2828
"Snippets"
2929
],
30-
"activationEvents": [
31-
"onCommand:pintia.openExtensionRepo"
32-
],
30+
"activationEvents": [],
3331
"main": "./out/extension",
3432
"contributes": {
3533
"viewsContainers": {
@@ -46,6 +44,11 @@
4644
{
4745
"id": "pintiaExplorer",
4846
"name": "%contributes.views.pintia.pintiaExplorer%"
47+
},
48+
{
49+
"id": "pintiaMyFavorites",
50+
"name": "%contributes.views.pintia.pintiaMyFavorites%",
51+
"visibility": "collapsed"
4952
}
5053
]
5154
},
@@ -63,6 +66,11 @@
6366
"when": "view == pintiaExplorer",
6467
"group": "navigation@0"
6568
},
69+
{
70+
"command": "pintia.signIn",
71+
"when": "view == pintiaExplorer",
72+
"group": "navigation@1"
73+
},
6674
{
6775
"command": "pintia.searchProblem",
6876
"when": "view == pintiaExplorer",
@@ -79,20 +87,47 @@
7987
"group": "navigation@4"
8088
},
8189
{
82-
"command": "pintia.signIn",
90+
"command": "pintia.signOut",
8391
"when": "view == pintiaExplorer",
8492
"group": "overflow@0"
8593
},
8694
{
87-
"command": "pintia.signOut",
95+
"command": "pintia.reportIssue",
8896
"when": "view == pintiaExplorer",
8997
"group": "overflow@1"
9098
},
9199
{
92-
"command": "pintia.reportIssue",
100+
"command": "pintia.openExtensionRepo",
93101
"when": "view == pintiaExplorer",
94102
"group": "overflow@2"
95103
}
104+
],
105+
"view/item/context": [
106+
{
107+
"command": "pintia.addFavorite",
108+
"when": "view == pintiaExplorer && viewItem == problem",
109+
"group": "inline"
110+
},
111+
{
112+
"command": "pintia.removeFavorite",
113+
"when": "view == pintiaExplorer && viewItem == problem-favorite",
114+
"group": "inline"
115+
},
116+
{
117+
"command": "pintia.removeFavorite",
118+
"when": "view == pintiaMyFavorites && viewItem == problem-favorite",
119+
"group": "inline"
120+
}
121+
],
122+
"commandPalette": [
123+
{
124+
"command": "pintia.addFavorite",
125+
"when": "never"
126+
},
127+
{
128+
"command": "pintia.removeFavorite",
129+
"when": "never"
130+
}
96131
]
97132
},
98133
"commands": [
@@ -166,6 +201,29 @@
166201
"command": "pintia.welcome",
167202
"title": "%contributes.commands.pintia.welcome%",
168203
"category": "Pintia"
204+
},
205+
{
206+
"command": "pintia.openExtensionRepo",
207+
"title": "%contributes.commands.pintia.openExtensionRepo%",
208+
"category": "Pintia"
209+
},
210+
{
211+
"command": "pintia.addFavorite",
212+
"title": "Add to Favorite List",
213+
"category": "Pintia",
214+
"icon": {
215+
"light": "resources/imgs/light/like.png",
216+
"dark": "resources/imgs/dark/like.png"
217+
}
218+
},
219+
{
220+
"command": "pintia.removeFavorite",
221+
"title": "Remove from Favorite List",
222+
"category": "Pintia",
223+
"icon": {
224+
"light": "resources/imgs/light/dislike.png",
225+
"dark": "resources/imgs/dark/dislike.png"
226+
}
169227
}
170228
],
171229
"configuration": {

package.nls.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
"contributes.commands.pintia.refreshProblemSearchIndex": "Refresh Problem Search Index",
1414
"contributes.commands.pintia.openWorkspace": "Open the Pintia Workspace",
1515
"contributes.commands.pintia.welcome": "Open Tutorial",
16+
"contributes.commands.pintia.openExtensionRepo": "Open PTA Repo",
1617
"contributes.views.pintia.pintiaExplorer": "Problems",
18+
"contributes.views.pintia.pintiaMyFavorites": "My Favorites",
1719
"contributes.viewsWelcome.pintiaExplorer": "Welcome to use the Pintia extension to practice PTA exercises. Please refer to the user manual for instructions on how to use this extension. Alternatively, visit the extension homepage at [vscode-pintia](https://github.com/jinzcdev/vscode-pintia) for more detailed information. \n[Sign in PTA](command:pintia.signIn) \n[Open Tutorial](command:pintia.welcome)",
1820
"configuration.pintia.workspaceFolder": "The path of the workspace folder to store the problem files.",
1921
"configuration.pintia.paging.pageSize": "Specify whether to page the problem list when the problem set is too large. It is not paged when pageSize is 0.",

package.nls.zh-cn.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"contributes.commands.pintia.openPintiaHome": "打开拼题A主页",
44
"contributes.commands.pintia.clearCache": "清除题目缓存",
55
"contributes.commands.pintia.signIn": "登录",
6-
"contributes.commands.pintia.signOut": "退出",
6+
"contributes.commands.pintia.signOut": "退出登录",
77
"contributes.commands.pintia.refreshExplorer": "刷新题目列表",
88
"contributes.commands.pintia.changeDefaultLanguage": "修改默认编程语言",
99
"contributes.commands.pintia.changeWorkspaceFolder": "修改工作区文件夹",
@@ -13,7 +13,9 @@
1313
"contributes.commands.pintia.refreshProblemSearchIndex": "刷新题目搜索索引",
1414
"contributes.commands.pintia.openWorkspace": "打开 Pintia 工作区",
1515
"contributes.commands.pintia.welcome": "查看插件使用指南",
16-
"contributes.views.pintia.pintiaExplorer": "固定题目集",
16+
"contributes.commands.pintia.openExtensionRepo": "打开插件仓库",
17+
"contributes.views.pintia.pintiaExplorer": "题目集",
18+
"contributes.views.pintia.pintiaMyFavorites": "我的收藏夹",
1719
"contributes.viewsWelcome.pintiaExplorer": "欢迎使用 Pintia 插件来练习拼题A习题。请查看使用手册以了解如何使用本插件。或者进入插件主页 [vscode-pintia](https://github.com/jinzcdev/vscode-pintia) 查看更详细的说明。\n[登录 PTA](command:pintia.signIn) \n[查看使用指南](command:pintia.welcome)",
1820
"configuration.pintia.workspaceFolder": "工作区文件夹的路径(存储题目源文件)。",
1921
"configuration.pintia.paging.pageSize": "指定当题目集较大时候,是否对题目列表分页。pageSize 为 0 表示不分页。",

resources/imgs/dark/dislike.png

364 Bytes
Loading

resources/imgs/dark/like.png

498 Bytes
Loading

resources/imgs/light/dislike.png

368 Bytes
Loading

resources/imgs/light/like.png

521 Bytes
Loading

src/commands/star.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { explorerController } from "../explorer/explorerController";
2+
import { PtaNode } from "../explorer/PtaNode";
3+
import { favoriteProblemsManager } from "../favorites/favoriteProblemsManager";
4+
import { favoritesTreeDataProvider } from "../favorites/favoritesTreeDataProvider";
5+
6+
export async function addFavoriteProblem(ptaNode: PtaNode) {
7+
favoriteProblemsManager.addFavoriteProblem(favoriteProblemsManager.getCurrentUserId(), {
8+
pID: ptaNode.pID,
9+
psID: ptaNode.psID,
10+
psName: ptaNode.value.problemSet,
11+
title: ptaNode.title
12+
});
13+
await favoritesTreeDataProvider.refresh();
14+
await explorerController.refreshTreeData();
15+
}
16+
17+
export async function removeFavoriteProblem(ptaNode: PtaNode) {
18+
favoriteProblemsManager.removeFavoriteProblem(favoriteProblemsManager.getCurrentUserId(), ptaNode.pID);
19+
await favoritesTreeDataProvider.refresh();
20+
await explorerController.refreshTreeData();
21+
}

src/explorer/PtaNode.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ export class PtaNode {
1717
return this.data.psID;
1818
}
1919

20+
public get title(): string {
21+
return this.data.title;
22+
}
23+
2024
public get label(): string {
2125
return this.data.label;
2226
}

src/explorer/PtaTreeDataProvider.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ export class PtaTreeDataProvider implements vscode.TreeDataProvider<PtaNode>, vs
4545
collapsibleState: vscode.TreeItemCollapsibleState.None
4646
}
4747
}
48+
let contextValue: string;
49+
if (element.type === PtaNodeType.Problem) {
50+
contextValue = element.isFavorite ? "problem-favorite" : "problem";
51+
} else {
52+
contextValue = "folder";
53+
}
4854
return {
4955
label: element.type === PtaNodeType.Problem ? `${element.label} (${element.score})` : element.label,
5056
collapsibleState: element.type === PtaNodeType.Problem ?
@@ -54,9 +60,11 @@ export class PtaTreeDataProvider implements vscode.TreeDataProvider<PtaNode>, vs
5460
title: "Preview Problem",
5561
command: "pintia.previewProblem",
5662
arguments: [element.psID, element.pID]
57-
} : undefined
63+
} : undefined,
64+
contextValue: contextValue
5865
};
5966
}
67+
6068
getChildren(element?: PtaNode): vscode.ProviderResult<PtaNode[]> {
6169
const limit: number = ptaConfig.getPageSize();
6270
const paged: boolean = limit !== 0;

src/explorer/explorerController.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class ExplorerController<T> implements Disposable {
2020
}
2121
}
2222

23-
public refreshTreeData() {
23+
public async refreshTreeData() {
2424
this.ptaTreeDataProvider?.refresh();
2525
}
2626

src/explorer/explorerNodeManager.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { IProblemInfo } from "../entity/IProblemInfo";
66
import { IProblemSet } from "../entity/IProblemSet";
77
import { IProblemSummary } from "../entity/IProblemSummary";
88
import { IUserSession } from "../entity/userLoginSession";
9+
import { favoriteProblemsManager } from "../favorites/favoriteProblemsManager";
910
import { ptaChannel } from "../ptaChannel";
1011
import { ptaConfig } from "../ptaConfig";
1112
import { ptaManager } from "../PtaManager";
@@ -115,18 +116,19 @@ class ExplorerNodeManager implements Disposable {
115116
});
116117
});
117118
}
118-
119119
const ptaNodeList: PtaNode[] = [];
120120
for (let i = 0; i < problemList.length; i++) {
121121
const pb: IProblemInfo = problemList[i];
122122
ptaNodeList.push(
123123
new PtaNode(Object.assign({}, defaultPtaNode, {
124124
pID: pb.id,
125125
psID: psID,
126+
title: `${pb.label} ${pb.title}`,
126127
label: `[${i + startIndex}] ${pb.label} ${pb.title}`,
127128
type: PtaNodeType.Problem,
128129
score: pb.score,
129130
state: problemExamMapping.get(pb.id) ?? ProblemSubmissionState.PROBLEM_NO_ANSWER,
131+
isFavorite: favoriteProblemsManager.isProblemFavorite(favoriteProblemsManager.getCurrentUserId(), pb.id),
130132
value: {
131133
problemType: problemType,
132134
problemInfo: pb,

src/extension.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ import * as show from "./commands/show";
77
import * as submit from "./commands/submit";
88
import * as user from "./commands/user";
99
import * as workspace from "./commands/workspace";
10+
import * as star from "./commands/star";
1011
import { explorerController } from "./explorer/explorerController";
12+
import { PtaNode } from "./explorer/PtaNode";
13+
import { favoritesTreeDataProvider } from "./favorites/favoritesTreeDataProvider";
1114
import { ptaChannel } from './ptaChannel';
1215
import { ptaExecutor } from './PtaExecutor';
1316
import { ptaManager } from './PtaManager';
@@ -17,6 +20,7 @@ import { ptaLoginProvider } from './webview/ptaLoginProvider';
1720
import { ptaPreviewProvider } from './webview/ptaPreviewProvider';
1821
import { ptaSubmissionProvider } from './webview/ptaSubmissionProvider';
1922
import { ptaTestProvider } from './webview/ptaTestProvider';
23+
import { favoriteProblemsManager } from "./favorites/favoriteProblemsManager";
2024

2125

2226
export async function activate(context: vscode.ExtensionContext) {
@@ -30,6 +34,7 @@ export async function activate(context: vscode.ExtensionContext) {
3034
explorerController.dispose();
3135
vscode.commands.executeCommand('setContext', 'pintia.showWelcome', true);
3236
}
37+
favoritesTreeDataProvider.refresh();
3338
ptaStatusBarController.updateStatusBar(ptaManager.getUserSession());
3439
});
3540

@@ -43,19 +48,21 @@ export async function activate(context: vscode.ExtensionContext) {
4348
ptaExecutor,
4449
ptaChannel,
4550
explorerController,
51+
favoriteProblemsManager,
52+
vscode.window.createTreeView("pintiaMyFavorites", { treeDataProvider: favoritesTreeDataProvider, showCollapseAll: true }),
4653
vscode.commands.registerCommand("pintia.openPintiaHome", () => user.openPintiaHome()),
4754
vscode.commands.registerCommand("pintia.openExtensionRepo", () => user.openExtensionRepo()),
4855
vscode.commands.registerCommand("pintia.refreshExplorer", () => explorerController.refreshTreeData()),
4956
vscode.commands.registerCommand("pintia.clearCache", () => cache.clearCache()),
5057
vscode.commands.registerCommand("pintia.signIn", () => ptaManager.signIn()),
5158
vscode.commands.registerCommand("pintia.signOut", () => ptaManager.signOut()),
52-
vscode.commands.registerCommand("pintia.previewProblem", async (psID: string, pID: string) => await ptaPreviewProvider.showPreview(psID, pID)),
59+
vscode.commands.registerCommand("pintia.previewProblem", (psID: string, pID: string) => ptaPreviewProvider.showPreview(psID, pID)),
5360
vscode.commands.registerCommand("pintia.manageUser", () => user.showUserManager()),
5461
vscode.commands.registerCommand("pintia.checkIn", () => user.checkInPTA()),
5562
vscode.commands.registerCommand("pintia.reportIssue", () => user.reportIssue()),
5663
vscode.commands.registerCommand("pintia.searchProblem", () => show.searchProblem()),
5764
vscode.commands.registerCommand("pintia.refreshProblemSearchIndex", () => cache.refreshProblemSearchIndex()),
58-
vscode.commands.registerCommand("pintia.codeProblem", async (ptaCode: IPtaCode) => await show.showCodingEditor(ptaCode)),
65+
vscode.commands.registerCommand("pintia.codeProblem", (ptaCode: IPtaCode) => show.showCodingEditor(ptaCode)),
5966
vscode.commands.registerCommand("pintia.testCustomSample", (ptaCode: IPtaCode, index: number) => submit.testCustomSample(ptaCode, index)),
6067
vscode.commands.registerCommand("pintia.submitSolution", (ptaCode: IPtaCode) => submit.submitSolution(ptaCode)),
6168
vscode.commands.registerCommand("pintia.testSolution", (ptaCode: IPtaCode) => submit.testSolution(ptaCode)),
@@ -65,6 +72,8 @@ export async function activate(context: vscode.ExtensionContext) {
6572
vscode.commands.registerCommand("pintia.welcome", () => {
6673
vscode.commands.executeCommand(`workbench.action.openWalkthrough`, `jinzcdev.vscode-pintia#pintia`, false);
6774
}),
75+
vscode.commands.registerCommand("pintia.addFavorite", (ptaNode: PtaNode) => star.addFavoriteProblem(ptaNode)),
76+
vscode.commands.registerCommand("pintia.removeFavorite", (ptaNode: PtaNode) => star.removeFavoriteProblem(ptaNode))
6877
);
6978

7079
await fs.mkdirs(configPath);

src/favorites/IFavoriteProblem.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
export interface IFavoriteProblem {
3+
pID: string;
4+
psID: string;
5+
psName: string;
6+
title: string;
7+
}

0 commit comments

Comments
 (0)