import 'dart:io'; import 'package:flutter/material.dart'; import 'package:path/path.dart' as p; class Sheet { final String author; final String name; final String path; Sheet(this.author, this.name, this.path); } Future> loadSheetsSorted(List sheetsDirectoryFiles) async { var sheets = await _loadSheets(sheetsDirectoryFiles); sheets.sort((left, right) => left.name.compareTo(right.name)); return sheets; } Future> _loadSheets(List sheetsDirectoryFiles) async { final List sheets = List.empty(growable: true); var authorDirectories = sheetsDirectoryFiles .map((e) => Directory(e)) .where((element) => element.existsSync()); for (Directory authorDirectory in authorDirectories) { var authorName = p.basename(authorDirectory.path); // Ignore hidden directories if (authorName.startsWith(".")) { continue; } await for (final FileSystemEntity sheetFile in authorDirectory.list()) { if (sheetFile is File) { var sheetName = p.basenameWithoutExtension(sheetFile.path); // Ignore hidden files if (sheetName.startsWith(".")) { continue; } sheetName = sheetName.capitalize(); sheets.add(Sheet(authorName, sheetName, sheetFile.path)); } } } return sheets; } extension StringExtension on String { String capitalize() { return "${this[0].toUpperCase()}${substring(1).toLowerCase()}"; } } class SheetsWidget extends StatelessWidget { final List sheets; final ValueSetter callback; const SheetsWidget({super.key, required this.sheets, required this.callback}); @override Widget build(context) { return ListView.builder( itemCount: sheets.length, itemBuilder: (context, index) { var sheet = sheets[index]; return ListTile( title: Text(sheet.name), subtitle: Text(sheet.author), onTap: () => callback(sheet), ); }); } }