From 0c79f86d80a2f43cf58c7fb2d0cb6c341df1d516 Mon Sep 17 00:00:00 2001 From: p-sw Date: Sat, 8 Jun 2024 04:10:13 +0900 Subject: [PATCH] refactor(cli): streamline component selection and overwrite process Refactored the 'cli add' command to streamline the process of component selection and the decision to overwrite an already installed one. The task has been split into two separate interactive choices to enhance the user experience and simplify the codebase. The force option is now also evaluated separately which results in cleaner code. --- packages/cli/src/commands/add.tsx | 107 ++++++++++++++++++------------ 1 file changed, 66 insertions(+), 41 deletions(-) diff --git a/packages/cli/src/commands/add.tsx b/packages/cli/src/commands/add.tsx index 9c91151..14d3077 100644 --- a/packages/cli/src/commands/add.tsx +++ b/packages/cli/src/commands/add.tsx @@ -5,7 +5,7 @@ import {mkdir, writeFile} from 'node:fs/promises' import {join} from 'node:path' import {getAvailableComponentNames, getComponentRealname, getComponentURL, getRegistry} from '../helpers/registry.js' import ora from 'ora' -import React, {ComponentPropsWithoutRef, useState} from 'react' +import React, {ComponentPropsWithoutRef} from 'react' import {render, Box} from 'ink' import {SearchBox} from '../components/SearchBox.js' import {getComponentsInstalled} from '../helpers/path.js' @@ -16,43 +16,18 @@ function Generator() { let complete: boolean = false function ComponentSelector( - props: Omit>, 'helper' | 'onSubmit'> & { - installed: string[] - onComplete: (value: T, force: 'yes' | 'no' | null) => void - skipForce: boolean - }, + props: Omit>, 'helper'>, ) { - const [forceStaged, setForceStaged] = useState(false) - const [onCompleteCache, setCache] = useState({key: '', displayName: '', installed: false} as T) - return ( - {!forceStaged ? ( - { - if (T.installed && !props.skipForce) { - setForceStaged(true) - setCache(T) - } else { - complete = true - props.onComplete(T, null) - } - }} - /> - ) : null} - {forceStaged ? ( - { - complete = true - props.onComplete(onCompleteCache, value) - }} - /> - ) : null} + { + complete = true + props.onSubmit?.(value) + }} + /> ) } @@ -70,6 +45,36 @@ function Generator() { ] as const } +function Generator2() { + let complete = false + + function ForceSelector({onComplete}: {onComplete: (value: 'yes' | 'no') => void}) { + return ( + { + complete = true + onComplete(value) + }} + /> + ) + } + + return [ + ForceSelector, + new Promise((r) => { + const i = setInterval(() => { + if (complete) { + r() + clearInterval(i) + } + }, 100) + }), + ] as const +} + export default class Add extends Command { static override args = { name: Args.string({description: 'name of component to install'}), @@ -121,7 +126,12 @@ export default class Add extends Command { })) let name: string | undefined = args.name?.toLowerCase?.() - let quit = false + let requireForce: boolean = + !name || !componentNames.includes(name.toLowerCase()) + ? false + : searchBoxComponent.find(({key}) => key === name)?.installed + ? !force + : false if (!name || !componentNames.includes(name.toLowerCase())) { const [ComponentSelector, waitForComplete] = Generator() @@ -130,12 +140,27 @@ export default class Add extends Command { { + onSubmit={(comp) => { name = comp.key - force = forceSelected === 'yes' - quit = forceSelected === 'no' + requireForce = comp.installed + inkInstance.clear() + }} + />, + ) + await waitForComplete + inkInstance.unmount() + } + + let quit = false + + if (requireForce) { + const [ForceSelector, waitForComplete] = Generator2() + + const inkInstance = render( + { + force = value === 'yes' + quit = value === 'no' inkInstance.clear() }} />,