runWizard function

Future<WizardRunResult> runWizard(
  1. WizardIo io, {
  2. String? initialProjectName,
  3. String? initialDescription,
  4. String? initialOrganization,
  5. String? initialDestination,
  6. String? initialFlutterSdkSource,
  7. Set<String>? initialTargetPlatforms,
  8. bool? initialGitPreference,
  9. ValidationProfile? initialValidationProfile,
})

Runs the interactive terminal wizard using the provided io.

Implementation

Future<WizardRunResult> runWizard(
  WizardIo io, {
  String? initialProjectName,
  String? initialDescription,
  String? initialOrganization,
  String? initialDestination,
  String? initialFlutterSdkSource,
  Set<String>? initialTargetPlatforms,
  bool? initialGitPreference,
  ValidationProfile? initialValidationProfile,
}) async {
  // Establish initial defaults
  String defaultProjectName = initialProjectName ?? 'my_app';
  String defaultDescription = initialDescription ?? 'A new Flutter project.';
  String defaultOrganization = initialOrganization ?? 'com.example';
  String defaultDestination = initialDestination ?? '';
  String defaultSdkSource = initialFlutterSdkSource ?? '';
  Set<String> defaultPlatforms = initialTargetPlatforms ?? supportedPlatforms;
  bool defaultGit = initialGitPreference ?? true;
  ValidationProfile defaultValProfile =
      initialValidationProfile ?? ValidationProfile.standard;

  while (true) {
    // 1. Project Name
    String projectName = '';
    while (true) {
      final input = io.prompt('Project name [$defaultProjectName]: ').trim();
      final val = input.isEmpty ? defaultProjectName : input;
      final res = validateProjectName(val);
      if (res is ValidationSuccess) {
        projectName = val;
        break;
      } else if (res is ValidationFailure) {
        io.writeLine('${res.ruleName}: ${res.message}');
      }
    }

    // 2. Description
    final descInput = io.prompt('Description [$defaultDescription]: ').trim();
    final description = descInput.isEmpty ? defaultDescription : descInput;

    // 3. Organization
    String organization = '';
    while (true) {
      final input = io.prompt('Organization [$defaultOrganization]: ').trim();
      final val = input.isEmpty ? defaultOrganization : input;
      final res = validateOrganization(val);
      if (res is ValidationSuccess) {
        organization = val;
        break;
      } else if (res is ValidationFailure) {
        io.writeLine('${res.ruleName}: ${res.message}');
      }
    }

    // 4. Destination
    final currentDefaultDestination = defaultDestination.isNotEmpty
        ? defaultDestination
        : './$projectName';
    final destInput = io
        .prompt('Destination [$currentDefaultDestination]: ')
        .trim();
    final destination = destInput.isEmpty
        ? currentDefaultDestination
        : destInput;

    // 5. Flutter SDK Source
    final displayDefaultSdk = defaultSdkSource.isEmpty
        ? 'none'
        : defaultSdkSource;
    final sdkInput = io
        .prompt('Flutter SDK source [$displayDefaultSdk]: ')
        .trim();
    final flutterSdkSource = (sdkInput.isEmpty || sdkInput == 'none')
        ? defaultSdkSource
        : sdkInput;

    // 6. Target Platforms
    Set<String> targetPlatforms = {};
    while (true) {
      final defaultPlatformsStr = defaultPlatforms.join(', ');
      final input = io
          .prompt('Target platforms ($defaultPlatformsStr): ')
          .trim();
      final Set<String> val;
      if (input.isEmpty) {
        val = defaultPlatforms;
      } else {
        val = input
            .split(',')
            .map((e) => e.trim())
            .where((e) => e.isNotEmpty)
            .toSet();
      }

      bool allValid = true;
      for (final p in val) {
        final res = validatePlatform(p);
        if (res is ValidationFailure) {
          io.writeLine('${res.ruleName}: ${res.message}');
          allValid = false;
          break;
        }
      }
      if (allValid && val.isNotEmpty) {
        targetPlatforms = val;
        break;
      } else if (val.isEmpty) {
        io.writeLine('At least one target platform must be selected.');
      }
    }

    // 7. Git Preference
    bool gitPreference = true;
    while (true) {
      final defaultGitStr = defaultGit ? 'yes' : 'no';
      final input = io
          .prompt('Initialize Git repository? (yes/no) [$defaultGitStr]: ')
          .trim()
          .toLowerCase();
      if (input.isEmpty) {
        gitPreference = defaultGit;
        break;
      } else if (input == 'yes' ||
          input == 'y' ||
          input == 'true' ||
          input == '1') {
        gitPreference = true;
        break;
      } else if (input == 'no' ||
          input == 'n' ||
          input == 'false' ||
          input == '0') {
        gitPreference = false;
        break;
      } else {
        io.writeLine("Invalid input. Please enter 'yes' or 'no'.");
      }
    }

    // 8. Validation Profile
    ValidationProfile validationProfile = ValidationProfile.standard;
    while (true) {
      final defaultValStr = defaultValProfile.name;
      final input = io.prompt('Validation profile [$defaultValStr]: ').trim();
      if (input.isEmpty) {
        validationProfile = defaultValProfile;
        break;
      } else if (input == 'standard') {
        validationProfile = ValidationProfile.standard;
        break;
      } else {
        io.writeLine(
          "Only 'standard' validation profile is supported in Release 0.1.",
        );
      }
    }

    // Display summary and stack
    displaySummary(
      io,
      projectName: projectName,
      description: description,
      organization: organization,
      destination: destination,
      flutterSdkSource: flutterSdkSource,
      targetPlatforms: targetPlatforms,
      gitPreference: gitPreference,
      validationProfile: validationProfile.name,
    );

    final action = promptSummaryAction(io);
    if (action == WizardAction.continueAction) {
      final blueprint = buildBlueprint(
        projectName: projectName,
        description: description,
        organization: organization,
        destination: destination,
        targetPlatforms: targetPlatforms,
        gitPreference: gitPreference,
        validationProfile: validationProfile,
      );
      return WizardRunSuccess(blueprint, flutterSdkSource: flutterSdkSource);
    } else if (action == WizardAction.cancelAction) {
      return const WizardRunCancelled();
    } else if (action == WizardAction.editAction) {
      // Prior answers become defaults
      defaultProjectName = projectName;
      defaultDescription = description;
      defaultOrganization = organization;
      defaultDestination = destination;
      defaultSdkSource = flutterSdkSource;
      defaultPlatforms = targetPlatforms;
      defaultGit = gitPreference;
      defaultValProfile = validationProfile;
    }
  }
}