Skip to content

Commit e3c21ad

Browse files
committed
feat: add config page
1 parent 3b68ba1 commit e3c21ad

10 files changed

Lines changed: 272 additions & 38 deletions

File tree

src/cli/cli.controller.ts

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
} from '../constants/index.js';
1212
import { ERROR_MSG, INFO_MSGS } from '../constants/messages.constants.js';
1313
import { IConfig, CliScanFoundFolder, IKeyPress } from './interfaces/index.js';
14-
import { firstValueFrom, Observable } from 'rxjs';
14+
import { firstValueFrom, Observable, Subject } from 'rxjs';
1515
import { filter, map, mergeMap, switchMap, tap } from 'rxjs/operators';
1616

1717
import { COLORS } from '../constants/cli.constants.js';
@@ -46,7 +46,6 @@ import { getFileContent } from '../utils/get-file-content.js';
4646
import { ResultDetailsUi } from './ui/components/result-details.ui.js';
4747

4848
export class CliController {
49-
private folderRoot = '';
5049
private readonly stdout: NodeJS.WriteStream = process.stdout;
5150
private readonly config: IConfig = DEFAULT_CONFIG;
5251

@@ -113,7 +112,7 @@ export class CliController {
113112
}
114113

115114
private initUi(): void {
116-
this.uiHeader = new HeaderUi();
115+
this.uiHeader = new HeaderUi(this.config);
117116
this.uiService.add(this.uiHeader);
118117
this.uiResults = new ResultsUi(this.resultsService, this.consoleService);
119118
this.uiService.add(this.uiResults);
@@ -144,14 +143,32 @@ export class CliController {
144143
}
145144

146145
private openOptions(): void {
147-
const optionsUi = new OptionsUi();
146+
const changeConfig$ = new Subject<Partial<IConfig>>();
147+
const optionsUi = new OptionsUi(changeConfig$, this.config);
148148
this.uiResults.clear();
149149
this.uiResults.setVisible(false);
150150
this.uiService.add(optionsUi);
151151
this.activeComponent = optionsUi;
152152
this.uiHeader.menuIndex$.next(MENU_BAR_OPTIONS.OPTIONS);
153153
this.uiService.renderAll();
154154

155+
changeConfig$.subscribe((configChanges) => {
156+
Object.assign(this.config, configChanges);
157+
if (
158+
configChanges.targetFolder ||
159+
configChanges.folderRoot ||
160+
configChanges.excludeHiddenDirectories ||
161+
configChanges.exclude
162+
) {
163+
this.scan();
164+
}
165+
if (configChanges.sortBy) {
166+
this.resultsService.sortResults(configChanges.sortBy);
167+
}
168+
this.logger.info(`Config updated: ${JSON.stringify(configChanges)}`);
169+
this.uiService.renderAll();
170+
});
171+
155172
optionsUi.goToHelp$.subscribe(() => {
156173
const helpUi = new HelpUi();
157174
this.uiService.add(helpUi);
@@ -240,11 +257,11 @@ export class CliController {
240257
this.config.exclude = [...this.config.exclude, ...userExcludeList];
241258
}
242259

243-
this.folderRoot = options.isTrue('directory')
260+
this.config.folderRoot = options.isTrue('directory')
244261
? options.getString('directory')
245262
: process.cwd();
246263
if (options.isTrue('full-scan')) {
247-
this.folderRoot = homedir();
264+
this.config.folderRoot = homedir();
248265
}
249266
if (options.isTrue('hide-errors')) {
250267
this.config.showErrors = false;
@@ -267,15 +284,14 @@ export class CliController {
267284

268285
if (options.isTrue('dry-run')) {
269286
this.config.dryRun = true;
270-
this.uiHeader.isDryRun = true;
271287
}
272288

273289
if (options.isTrue('yes')) {
274290
this.config.yes = true;
275291
}
276292

277293
// Remove trailing slash from folderRoot for consistency
278-
this.folderRoot = this.folderRoot.replace(/[/\\]$/, '');
294+
this.config.folderRoot = this.config.folderRoot.replace(/[/\\]$/, '');
279295
}
280296

281297
private showErrorPopup(visible: boolean): void {
@@ -356,7 +372,7 @@ export class CliController {
356372
}
357373

358374
private checkFileRequirements(): void {
359-
const result = this.npkill.isValidRootFolder(this.folderRoot);
375+
const result = this.npkill.isValidRootFolder(this.config.folderRoot);
360376
if (!result.isValid) {
361377
const errorMessage =
362378
result.invalidReason || 'Root folder is not valid. Unknown reason';
@@ -437,6 +453,9 @@ export class CliController {
437453
}
438454

439455
private scan(): void {
456+
this.searchStatus.reset();
457+
this.resultsService.reset();
458+
this.uiStatus.reset();
440459
this.uiStatus.start();
441460

442461
const params = this.prepareListDirParams();
@@ -495,7 +514,7 @@ export class CliController {
495514
private prepareListDirParams() {
496515
const target = this.config.targetFolder;
497516
const params = {
498-
rootPath: this.folderRoot,
517+
rootPath: this.config.folderRoot,
499518
targets: [target],
500519
};
501520

src/cli/interfaces/config.interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export interface IConfig {
2+
folderRoot: string;
23
backgroundColor: string;
34
warningColor: string;
45
checkUpdates: boolean;

src/cli/interfaces/key-press.interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ export interface IKeyPress {
33
meta: boolean;
44
ctrl: boolean;
55
shift: boolean;
6+
sequence: string;
67
}

src/cli/services/results.service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ export class ResultsService {
1212
this.results = this.results.sort(FOLDER_SORT[method]);
1313
}
1414

15+
reset(): void {
16+
this.results = [];
17+
}
18+
1519
getStats(): IStats {
1620
let spaceReleased = 0;
1721

src/cli/ui/components/header/header.ui.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
} from '../../../../constants/index.js';
99
import { BaseUi } from '../../base.ui.js';
1010
import colors from 'colors';
11+
import { IConfig } from 'src/cli/interfaces/config.interface.js';
1112

1213
export enum MENU_BAR_OPTIONS {
1314
HELP = 0,
@@ -18,14 +19,13 @@ export enum MENU_BAR_OPTIONS {
1819

1920
export class HeaderUi extends BaseUi {
2021
programVersion: string;
21-
isDryRun: boolean;
2222
private activeMenuIndex = MENU_BAR_OPTIONS.DELETE;
2323

2424
readonly menuIndex$ = new BehaviorSubject<MENU_BAR_OPTIONS>(
2525
MENU_BAR_OPTIONS.DELETE,
2626
);
2727

28-
constructor() {
28+
constructor(private readonly config: IConfig) {
2929
super();
3030
this.menuIndex$.subscribe((menuIndex) => {
3131
this.activeMenuIndex = menuIndex;
@@ -43,7 +43,7 @@ export class HeaderUi extends BaseUi {
4343
this.printAt(colors.gray(this.programVersion), UI_POSITIONS.VERSION);
4444
}
4545

46-
if (this.isDryRun) {
46+
if (this.config.dryRun) {
4747
this.printAt(
4848
colors.black(colors.bgMagenta(` ${INFO_MSGS.DRY_RUN} `)),
4949
UI_POSITIONS.DRY_RUN_NOTICE,

src/cli/ui/components/header/status.ui.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export class StatusUi extends BaseUi {
2020
private barClosing = false;
2121
private showProgressBar = true;
2222
private pendingTasksPosition = { ...UI_POSITIONS.PENDING_TASKS };
23-
private readonly searchEnd$ = new Subject();
23+
private searchEnd$ = new Subject();
2424
private readonly SEARCH_STATES = {
2525
stopped: () => this.startingSearch(),
2626
scanning: () => this.continueSearching(),
@@ -36,6 +36,8 @@ export class StatusUi extends BaseUi {
3636
}
3737

3838
start(): void {
39+
this.barClosing = false;
40+
this.showProgressBar = true;
3941
this.spinnerService.setSpinner(SPINNERS.W10);
4042
interval(SPINNER_INTERVAL)
4143
.pipe(takeUntil(this.searchEnd$))
@@ -46,6 +48,19 @@ export class StatusUi extends BaseUi {
4648
this.animateProgressBar();
4749
}
4850

51+
reset(): void {
52+
this.barClosing = false;
53+
this.showProgressBar = true;
54+
this.barNormalizedWidth = 0;
55+
this.text = '';
56+
this.pendingTasksPosition = { ...UI_POSITIONS.PENDING_TASKS };
57+
this.searchEnd$.next(true);
58+
this.searchEnd$ = new Subject();
59+
60+
this.clearPendingTasks();
61+
this.render();
62+
}
63+
4964
completeSearch(duration: number): void {
5065
this.searchEnd$.next(true);
5166
this.searchEnd$.complete();
@@ -57,7 +72,7 @@ export class StatusUi extends BaseUi {
5772
}
5873

5974
render(): void {
60-
this.printAt(this.text, UI_POSITIONS.STATUS);
75+
this.printAt(this.text + ' ', UI_POSITIONS.STATUS);
6176

6277
if (this.showProgressBar) {
6378
this.renderProgressBar();

0 commit comments

Comments
 (0)