scan method
Implementation
Future<void> scan(List<String> roots, {bool replace = true, void Function(int scanned, int total)? onProgress}) async {
if (kIsWeb || _scanning) return;
_scanning = true;
_scanned = 0;
_scanTotal = 0;
notifyListeners();
final List<String> files = <String>[];
for (final String root in roots) {
try {
await for (final FileSystemEntity entity in Directory(root).list(recursive: true, followLinks: false)) {
if (entity is! File) continue;
final String lower = entity.path.toLowerCase();
final int dot = lower.lastIndexOf(".");
if (dot < 0 || !UAudio.audioExtensions.contains(lower.substring(dot))) continue;
files.add(entity.path);
}
} on FileSystemException {
continue;
}
}
_scanTotal = files.length;
notifyListeners();
final Map<String, UTrackRecord> existing = <String, UTrackRecord>{for (final UTrackRecord record in _tracks) record.path: record};
final List<UTrackRecord> result = <UTrackRecord>[];
final int now = DateTime.now().millisecondsSinceEpoch;
for (final String path in files) {
_scanned++;
if (_scanned % 25 == 0) {
onProgress?.call(_scanned, _scanTotal);
notifyListeners();
await Future<void>.delayed(Duration.zero);
}
final UTrackRecord? cached = existing[path];
if (cached != null && !replace) {
result.add(cached);
continue;
}
final UMediaMetadata tags = await UTagParser.readFile(path);
int size = 0;
try {
size = await File(path).length();
} on FileSystemException {
size = 0;
}
final String fallbackTitle = path.split(Platform.pathSeparator).last.replaceAll(RegExp(r"\.[^.]+$"), "");
result.add(
UTrackRecord(
path: path,
title: tags.title ?? fallbackTitle,
artist: tags.artist ?? "",
album: tags.album ?? "",
albumArtist: tags.albumArtist,
genre: tags.genre,
year: tags.year,
trackNumber: tags.trackNumber,
discNumber: tags.discNumber,
durationMs: tags.duration?.inMilliseconds ?? 0,
sizeBytes: size,
addedAt: cached?.addedAt ?? now,
artworkOffset: tags.artwork?.offset ?? 0,
artworkLength: tags.artwork?.length ?? 0,
artworkMime: tags.artwork?.mimeType,
),
);
}
_tracks
..clear()
..addAll(result);
_scanning = false;
_scanned = _scanTotal;
notifyListeners();
await save();
}