listClients function

void listClients()

Lists all currently available Clonify project clones.

This function scans the ./clonify/clones directory, reads the config.json file for each found client, and then prints a formatted table displaying the Client ID, App Name, Firebase Project ID, and Version for each clone.

If no clones are found or if there are errors parsing configuration files, appropriate messages are logged.

Implementation

void listClients() async {
  infoMessage('\nπŸ“‹ Available Clones');

  final dir = Directory('./clonify/clones');
  if (!dir.existsSync()) {
    warningMessage('No clones directory found.');
    infoMessage(
      'Run "clonify init" to initialize, then "clonify create" to create your first clone.',
    );
    return;
  }

  // Get last active client
  final lastClientId = await getLastClientId();

  // Column Widths (adjust as needed)
  int clientIdWidth = 15;
  int appNameWidth = 20;
  int firebaseProjectIdWidth = 30;
  const int versionWidth = 12;

  final List<Map<String, String>> clientsData = [];

  for (final entity in dir.listSync()) {
    if (entity is Directory) {
      final configFile = File('${entity.path}/config.json');
      if (configFile.existsSync()) {
        try {
          final content = jsonDecode(configFile.readAsStringSync());
          final clientId = content['clientId'] ?? '';
          final appName = content['appName'] ?? '';
          final firebaseProjectId = content['firebaseProjectId'] ?? '';
          final version = content['version']?.toString() ?? 'N/A';

          // Adjust column widths
          clientIdWidth = clientId.length > clientIdWidth
              ? clientId.length
              : clientIdWidth;
          appNameWidth = appName.length > appNameWidth
              ? appName.length
              : appNameWidth;
          firebaseProjectIdWidth =
              firebaseProjectId.length > firebaseProjectIdWidth
              ? firebaseProjectId.length
              : firebaseProjectIdWidth;

          clientsData.add({
            'clientId': clientId,
            'appName': appName,
            'firebaseProjectId': firebaseProjectId,
            'version': version,
          });
        } catch (e) {
          errorMessage('Error parsing config file: $e');
        }
      }
    }
  }

  if (clientsData.isEmpty) {
    warningMessage('No clones found.');
    infoMessage('Create your first clone with: clonify create');
    return;
  }

  // Print styled table header
  if (isTUIEnabled()) {
    final chalk = Chalk();
    final headerLine =
        '+${'─' * (clientIdWidth + appNameWidth + firebaseProjectIdWidth + versionWidth + 10)}+';
    print(chalk.cyan(headerLine));

    final header =
        '| '
        '${'πŸ†” Client ID'.padRight(clientIdWidth + 2)}| '
        '${'πŸ“± App Name'.padRight(appNameWidth + 2)}| '
        '${'πŸ”₯ Firebase'.padRight(firebaseProjectIdWidth + 2)}| '
        '${'πŸ”’ Version'.padRight(versionWidth + 2)}|';
    print(chalk.cyan.bold(header));
    print(chalk.cyan(headerLine));
  } else {
    // Basic table for non-TUI mode
    final headerLine =
        '+${'─' * (clientIdWidth + appNameWidth + firebaseProjectIdWidth + versionWidth + 7)}+';
    logger.i('\n$headerLine');
    logger.i(
      '| ${'Client ID'.padRight(clientIdWidth)}|'
      ' ${'App Name'.padRight(appNameWidth)}|'
      ' ${'Firebase Project ID'.padRight(firebaseProjectIdWidth)}|'
      ' ${'Version'.padRight(versionWidth)}|',
    );
    logger.i(headerLine);
  }

  // Print table rows with highlighting for active client
  for (final client in clientsData) {
    final isActive = client['clientId'] == lastClientId;
    final row =
        '| '
        '${client['clientId']!.padRight(clientIdWidth)}| '
        '${client['appName']!.padRight(appNameWidth)}| '
        '${(client['firebaseProjectId'] ?? '').padRight(firebaseProjectIdWidth)}| '
        '${client['version']!.padRight(versionWidth)}|';

    if (isTUIEnabled()) {
      final chalk = Chalk();
      if (isActive) {
        print(chalk.green.bold('β–Ά ${row.substring(2)}'));
      } else {
        print(chalk.white('  $row'));
      }
    } else {
      if (isActive) {
        logger.i('β–Ά $row');
      } else {
        logger.i(row);
      }
    }
  }

  // Print table footer
  if (isTUIEnabled()) {
    final chalk = Chalk();
    final footerLine =
        '+${'─' * (clientIdWidth + appNameWidth + firebaseProjectIdWidth + versionWidth + 10)}+';
    print(chalk.cyan(footerLine));
  } else {
    final footerLine =
        '+${'─' * (clientIdWidth + appNameWidth + firebaseProjectIdWidth + versionWidth + 7)}+';
    logger.i(footerLine);
  }

  // Display summary
  final totalClones = clientsData.length;
  if (isTUIEnabled()) {
    print('');
    if (lastClientId != null) {
      successMessage('πŸ“Œ Active Clone: $lastClientId');
    }
    infoMessage('πŸ“Š Total Clones: $totalClones');
  } else {
    logger.i('');
    if (lastClientId != null) {
      logger.i('Active client: $lastClientId');
    }
    logger.i('Total clients: $totalClones');
  }
}