scan method

Future<void> scan(
  1. List<String> roots, {
  2. bool replace = true,
  3. void onProgress(
    1. int scanned,
    2. int total
    )?,
})

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();
}