@@ -5,30 +5,21 @@ import * as _ from "lodash";
55import * as os from "os" ;
66import * as path from "path" ;
77import * as vscode from "vscode" ;
8- import * as list from "../commands/list" ;
9- import { leetCodeChannel } from "../leetCodeChannel" ;
108import { leetCodeManager } from "../leetCodeManager" ;
11- import { Category , defaultProblem , IProblem , ProblemState } from "../shared" ;
12- import { getWorkspaceConfiguration } from "../utils/workspaceUtils " ;
9+ import { Category , defaultProblem , ProblemState } from "../shared" ;
10+ import { explorerNodeManager } from "./explorerNodeManager " ;
1311import { LeetCodeNode } from "./LeetCodeNode" ;
1412
1513export class LeetCodeTreeDataProvider implements vscode . TreeDataProvider < LeetCodeNode > {
1614
17- private treeData : {
18- Difficulty : Map < string , IProblem [ ] > ,
19- Tag : Map < string , IProblem [ ] > ,
20- Company : Map < string , IProblem [ ] > ,
21- Favorite : IProblem [ ] ,
22- } ;
23-
2415 private onDidChangeTreeDataEvent : vscode . EventEmitter < any > = new vscode . EventEmitter < any > ( ) ;
2516 // tslint:disable-next-line:member-ordering
2617 public readonly onDidChangeTreeData : vscode . Event < any > = this . onDidChangeTreeDataEvent . event ;
2718
2819 constructor ( private context : vscode . ExtensionContext ) { }
2920
3021 public async refresh ( ) : Promise < void > {
31- await this . getProblemData ( ) ;
22+ await explorerNodeManager . refreshCache ( ) ;
3223 this . onDidChangeTreeDataEvent . fire ( ) ;
3324 }
3425
@@ -49,7 +40,7 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider<LeetCod
4940 return {
5041 label : element . isProblem ? `[${ element . id } ] ${ element . name } ` : element . name ,
5142 tooltip : this . getSubCategoryTooltip ( element ) ,
52- id : `${ idPrefix } .${ element . parentName } . ${ element . id } ` ,
43+ id : `${ idPrefix } .${ element . id } ` ,
5344 collapsibleState : element . isProblem ? vscode . TreeItemCollapsibleState . None : vscode . TreeItemCollapsibleState . Collapsed ,
5445 contextValue : element . isProblem ? "problem" : element . id . toLowerCase ( ) ,
5546 iconPath : this . parseIconPathFromProblemState ( element ) ,
@@ -63,93 +54,38 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider<LeetCod
6354 new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
6455 id : "notSignIn" ,
6556 name : "Sign in to LeetCode" ,
66- } ) , "ROOT" , false ) ,
57+ } ) , false ) ,
6758 ] ;
6859 }
6960 if ( ! element ) { // Root view
70- return [
71- new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
72- id : Category . Difficulty ,
73- name : Category . Difficulty ,
74- } ) , "ROOT" , false ) ,
75- new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
76- id : Category . Tag ,
77- name : Category . Tag ,
78- } ) , "ROOT" , false ) ,
79- new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
80- id : Category . Company ,
81- name : Category . Company ,
82- } ) , "ROOT" , false ) ,
83- new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
84- id : Category . Favorite ,
85- name : Category . Favorite ,
86- } ) , "ROOT" , false ) ,
87- ] ;
61+ return explorerNodeManager . getRootNodes ( ) ;
8862 } else {
89- switch ( element . name ) { // First-level
63+ let res : LeetCodeNode [ ] = [ ] ;
64+ switch ( element . id ) { // First-level
9065 case Category . Favorite :
91- const nodes : IProblem [ ] = this . treeData [ Category . Favorite ] ;
92- return nodes . map ( ( p : IProblem ) => new LeetCodeNode ( p , Category . Favorite ) ) ;
66+ res = explorerNodeManager . getFavoriteNodes ( ) ;
67+ break ;
9368 case Category . Difficulty :
69+ res = explorerNodeManager . getAllDifficultyNodes ( ) ;
70+ break ;
9471 case Category . Tag :
72+ res = explorerNodeManager . getAllTagNodes ( ) ;
73+ break ;
9574 case Category . Company :
96- return this . composeSubCategoryNodes ( element ) ;
97- default : // Second and lower levels
98- return element . isProblem ? [ ] : this . composeProblemNodes ( element ) ;
99- }
100- }
101- }
102-
103- private async getProblemData ( ) : Promise < void > {
104- // clear cache
105- this . treeData = {
106- Difficulty : new Map < string , IProblem [ ] > ( ) ,
107- Tag : new Map < string , IProblem [ ] > ( ) ,
108- Company : new Map < string , IProblem [ ] > ( ) ,
109- Favorite : [ ] ,
110- } ;
111- for ( const problem of await list . listProblems ( ) ) {
112- // Add favorite problem, no matter whether it is solved.
113- if ( problem . isFavorite ) {
114- this . treeData [ Category . Favorite ] . push ( problem ) ;
115- }
116- // Hide solved problem in other category.
117- if ( problem . state === ProblemState . AC && getWorkspaceConfiguration ( ) . get < boolean > ( "hideSolved" ) ) {
118- continue ;
75+ res = explorerNodeManager . getAllCompanyNodes ( ) ;
76+ break ;
77+ default :
78+ if ( element . isProblem ) {
79+ break ;
80+ }
81+ res = explorerNodeManager . getChildrenNodesById ( element . id ) ;
82+ break ;
11983 }
120-
121- this . addProblemToTreeData ( problem ) ;
84+ element . setChildrenNodes ( res ) ;
85+ return res ;
12286 }
12387 }
12488
125- private composeProblemNodes ( node : LeetCodeNode ) : LeetCodeNode [ ] {
126- const map : Map < string , IProblem [ ] > | undefined = this . treeData [ node . parentName ] ;
127- if ( ! map ) {
128- leetCodeChannel . appendLine ( `Category: ${ node . parentName } is not available.` ) ;
129- return [ ] ;
130- }
131- const problems : IProblem [ ] = map . get ( node . name ) || [ ] ;
132- const problemNodes : LeetCodeNode [ ] = [ ] ;
133- for ( const problem of problems ) {
134- problemNodes . push ( new LeetCodeNode ( problem , node . name ) ) ;
135- }
136- return problemNodes ;
137- }
138-
139- private composeSubCategoryNodes ( node : LeetCodeNode ) : LeetCodeNode [ ] {
140- const category : Category = node . name as Category ;
141- if ( category === Category . Favorite ) {
142- leetCodeChannel . appendLine ( "No sub-level for Favorite nodes" ) ;
143- return [ ] ;
144- }
145- const map : Map < string , IProblem [ ] > | undefined = this . treeData [ category ] ;
146- if ( ! map ) {
147- leetCodeChannel . appendLine ( `Category: ${ category } is not available.` ) ;
148- return [ ] ;
149- }
150- return this . getSubCategoryNodes ( map , category ) ;
151- }
152-
15389 private parseIconPathFromProblemState ( element : LeetCodeNode ) : string {
15490 if ( ! element . isProblem ) {
15591 return "" ;
@@ -171,16 +107,16 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider<LeetCod
171107
172108 private getSubCategoryTooltip ( element : LeetCodeNode ) : string {
173109 // return '' unless it is a sub-category node
174- if ( element . isProblem || ! this . treeData [ element . parentName ] ) {
110+ if ( element . isProblem || element . id === "ROOT" || element . id in Category ) {
175111 return "" ;
176112 }
177113
178- const problems : IProblem [ ] = this . treeData [ element . parentName ] . get ( element . id ) ;
114+ const childernNodes : LeetCodeNode [ ] = explorerNodeManager . getChildrenNodesById ( element . id ) ;
179115
180116 let acceptedNum : number = 0 ;
181117 let failedNum : number = 0 ;
182- for ( const prob of problems ) {
183- switch ( prob . state ) {
118+ for ( const node of childernNodes ) {
119+ switch ( node . state ) {
184120 case ProblemState . AC :
185121 acceptedNum ++ ;
186122 break ;
@@ -195,73 +131,7 @@ export class LeetCodeTreeDataProvider implements vscode.TreeDataProvider<LeetCod
195131 return [
196132 `AC: ${ acceptedNum } ` ,
197133 `Failed: ${ failedNum } ` ,
198- `Total: ${ problems . length } ` ,
134+ `Total: ${ childernNodes . length } ` ,
199135 ] . join ( os . EOL ) ;
200136 }
201-
202- private addProblemToTreeData ( problem : IProblem ) : void {
203- this . putProblemToMap ( this . treeData . Difficulty , problem . difficulty , problem ) ;
204- for ( const tag of problem . tags ) {
205- this . putProblemToMap ( this . treeData . Tag , _ . startCase ( tag ) , problem ) ;
206- }
207- for ( const company of problem . companies ) {
208- this . putProblemToMap ( this . treeData . Company , _ . startCase ( company ) , problem ) ;
209- }
210- }
211-
212- private putProblemToMap ( map : Map < string , IProblem [ ] > , key : string , problem : IProblem ) : void {
213- const problems : IProblem [ ] | undefined = map . get ( key ) ;
214- if ( problems ) {
215- problems . push ( problem ) ;
216- } else {
217- map . set ( key , [ problem ] ) ;
218- }
219- }
220-
221- private getSubCategoryNodes ( map : Map < string , IProblem [ ] > , category : Category ) : LeetCodeNode [ ] {
222- const subCategoryNodes : LeetCodeNode [ ] = Array . from ( map . keys ( ) ) . map ( ( subCategory : string ) => {
223- return new LeetCodeNode ( Object . assign ( { } , defaultProblem , {
224- id : subCategory ,
225- name : subCategory ,
226- } ) , category . toString ( ) , false ) ;
227- } ) ;
228- this . sortSubCategoryNodes ( subCategoryNodes , category ) ;
229- return subCategoryNodes ;
230- }
231-
232- private sortSubCategoryNodes ( subCategoryNodes : LeetCodeNode [ ] , category : Category ) : void {
233- switch ( category ) {
234- case Category . Difficulty :
235- subCategoryNodes . sort ( ( a : LeetCodeNode , b : LeetCodeNode ) : number => {
236- function getValue ( input : LeetCodeNode ) : number {
237- switch ( input . name . toLowerCase ( ) ) {
238- case "easy" :
239- return 1 ;
240- case "medium" :
241- return 2 ;
242- case "hard" :
243- return 3 ;
244- default :
245- return Number . MAX_SAFE_INTEGER ;
246- }
247- }
248- return getValue ( a ) - getValue ( b ) ;
249- } ) ;
250- break ;
251- case Category . Tag :
252- case Category . Company :
253- subCategoryNodes . sort ( ( a : LeetCodeNode , b : LeetCodeNode ) : number => {
254- if ( a . name === "Unknown" ) {
255- return 1 ;
256- } else if ( b . name === "Unknown" ) {
257- return - 1 ;
258- } else {
259- return Number ( a . name > b . name ) - Number ( a . name < b . name ) ;
260- }
261- } ) ;
262- break ;
263- default :
264- break ;
265- }
266- }
267137}
0 commit comments