refactor(installer): improve spinner handling during IDE setup

- Added logic to stop the spinner before calling setup() to prevent prompts from interfering with the spinner display.
- Restarted the spinner after setup() completes to maintain user feedback during IDE configuration updates.
- Enhanced configuration collection process in ClaudeCodeSetup to ensure user inputs are gathered before cleanup, improving user experience during setup.
This commit is contained in:
Phil Mahncke 2025-11-12 10:48:53 -05:00
parent 74f54a088a
commit aac1abf6e4
2 changed files with 53 additions and 26 deletions

View File

@ -1638,12 +1638,22 @@ class Installer {
spinner.start('Updating IDE configurations...');
for (const ide of toolConfig.ides) {
spinner.text = `Updating ${ide}...`;
// Stop spinner before setup() since it may prompt for configuration
// (setup() doesn't have preCollectedConfig in compile flow)
if (spinner.isSpinning) {
spinner.stop();
}
await this.ideManager.setup(ide, projectDir, bmadDir, {
selectedModules: installedModules,
skipModuleInstall: true, // Skip module installation, just update IDE files
verbose: config.verbose,
});
// Restart spinner after setup() completes (prompts are done)
if (!spinner.isSpinning) {
spinner.start('Updating IDE configurations...');
}
}
spinner.succeed('IDE configurations updated');

View File

@ -108,7 +108,14 @@ class ClaudeCodeSetup extends BaseIdeSetup {
console.log(chalk.cyan(`Setting up ${this.name}...`));
// Clean up old BMAD installation first
// Collect configuration BEFORE cleanup to avoid deleting files before user answers
let preCollectedConfig = options.preCollectedConfig;
if (!preCollectedConfig || !preCollectedConfig._alreadyConfigured) {
// Collect configuration interactively if not already provided
preCollectedConfig = await this.collectConfiguration(options);
}
// Clean up old BMAD installation AFTER collecting configuration
await this.cleanup(projectDir);
// Create .claude/commands directory structure
@ -139,12 +146,12 @@ class ClaudeCodeSetup extends BaseIdeSetup {
// Process Claude Code specific injections for installed modules
// Use pre-collected configuration if available, or skip if already configured
if (options.preCollectedConfig && options.preCollectedConfig._alreadyConfigured) {
if (preCollectedConfig?._alreadyConfigured) {
// IDE is already configured from previous installation, skip prompting
// Just process with default/existing configuration
await this.processModuleInjectionsWithConfig(projectDir, bmadDir, options, {});
} else if (options.preCollectedConfig) {
await this.processModuleInjectionsWithConfig(projectDir, bmadDir, options, options.preCollectedConfig);
} else if (preCollectedConfig) {
await this.processModuleInjectionsWithConfig(projectDir, bmadDir, options, preCollectedConfig);
} else {
await this.processModuleInjections(projectDir, bmadDir, options);
}
@ -291,21 +298,14 @@ class ClaudeCodeSetup extends BaseIdeSetup {
let choices = subagentChoices;
let location = installLocation;
// Collect configuration ONCE before processing modules if interactive and not already collected
if (interactive && !choices) {
// Check if any module has subagents before prompting
for (const moduleName of modules) {
const configData = await loadModuleInjectionConfig(handler, moduleName);
if (!configData) {
continue;
}
const { config, handlerBaseDir } = configData;
if (interactive) {
console.log(chalk.cyan(`\nConfiguring ${moduleName} ${handler.replace('-', ' ')} features...`));
}
if (interactive && config.subagents && !choices) {
choices = await this.promptSubagentInstallation(config.subagents);
if (configData?.config?.subagents) {
// Use the first module's config for prompting (they should all be similar)
choices = await this.promptSubagentInstallation(configData.config.subagents);
if (choices.install !== 'none') {
const inquirer = require('inquirer');
@ -323,6 +323,23 @@ class ClaudeCodeSetup extends BaseIdeSetup {
]);
location = locationAnswer.location;
}
break; // Only prompt once
}
}
}
// Now process each module with the collected configuration
for (const moduleName of modules) {
const configData = await loadModuleInjectionConfig(handler, moduleName);
if (!configData) {
continue;
}
const { config, handlerBaseDir } = configData;
if (interactive) {
console.log(chalk.cyan(`\nConfiguring ${moduleName} ${handler.replace('-', ' ')} features...`));
}
if (config.injections && choices && choices.install !== 'none') {