refactor(services): clarify misleading names and drop a no-op rethrow

Remove the try/catch that only rethrew in the library scan helper, rename
the history loader that schedules a microtask, and fix two comments.
This commit is contained in:
zarzet committed 2026-10-18 22:12:29 +07:00
1 parent 019257541b
commit 6879df4917
3 files changed
+63 -64

No files matched your search

+2 -2
View File
@@ -118,11 +118,11 @@ class DownloadHistoryNotifier extends Notifier<DownloadHistoryState> {
@override
DownloadHistoryState build() {
ref.onDispose(() => _indexBumpTimer?.cancel());
_loadFromDatabaseSync();
_scheduleLoadFromDatabase();
return DownloadHistoryState();
}
void _loadFromDatabaseSync() {
void _scheduleLoadFromDatabase() {
if (_isLoaded) return;
_isLoaded = true;
Future.microtask(() async {
+4 -1
View File
@@ -52,7 +52,8 @@ class HistoryBatchLookupRequest {
const HistoryBatchLookupRequest(this.tracks);
/// An immutable request whose hash is computed only once. Use for lists
/// retained across widget builds; the legacy constructor remains available.
/// retained across widget builds; the const constructor recomputes the hash
/// on every use.
factory HistoryBatchLookupRequest.snapshot(
Iterable<HistoryLookupRequest> tracks,
) = _HistoryBatchLookupSnapshot;
@@ -339,6 +340,8 @@ class HistoryDatabase {
return (value ?? '').trim().toLowerCase();
}
/// Returns '' for an empty track name, unlike [LibraryDatabase.matchKeyFor],
/// which returns '|artist' in that case.
static String matchKeyFor(String? trackName, String? artistName) {
final track = normalizeLookupText(trackName);
if (track.isEmpty) return '';
+57 -61
View File
@@ -2479,68 +2479,64 @@ class PlatformBridge {
'${scanDir.path}${Platform.pathSeparator}'
'library_scan_${hash.toRadixString(16).padLeft(8, '0')}.ndjson',
);
try {
if (isCancelled?.call() == true) {
throw StateError('Library scan cancelled before native scan');
}
if (forceFullScan) {
// An explicit rescan must not resume metadata from an earlier attempt.
for (final file in [output, File('${output.path}.state')]) {
if (await file.exists()) await file.delete();
}
// Preserve covers referenced by the current DB until ingestion succeeds.
// Fresh paths bypass native disk and Flutter image caches together.
final covers = Directory('${scanDir.path}/library_covers');
await covers.create(recursive: true);
final freshCovers = await covers.createTemp('full_scan_');
await setLibraryCoverCacheDir(freshCovers.path);
}
if (isCancelled?.call() == true) {
throw StateError('Library scan cancelled before native scan');
}
final result = await _channel.invokeMethod(method, {
...arguments,
'output_path': output.path,
});
if (result is! Map) {
throw FormatException('$method returned ${result.runtimeType}');
}
if (result['cancelled'] == true) {
throw FormatException('$method returned a cancelled partial scan');
}
final errors = result['error_count'];
if (errors is! num ||
!errors.isFinite ||
errors < 0 ||
errors != errors.toInt()) {
throw FormatException('$method returned an invalid error count');
}
final pathValue = result['path'];
final countValue = result['count'];
if (pathValue is! String || pathValue.trim().isEmpty) {
throw FormatException('$method returned an invalid output path');
}
if (countValue is! num ||
!countValue.isFinite ||
countValue < 0 ||
countValue != countValue.toInt()) {
throw FormatException('$method returned an invalid row count');
}
final path = pathValue;
final count = countValue.toInt();
final file = File(path);
if (!await file.exists()) {
throw FormatException('$method did not create its output file');
}
return LibraryScanNDJSONFile(
file: file,
expectedCount: count,
errorCount: errors.toInt(),
);
} catch (_) {
// Keep partial output; native SAF scan resumes from its sidecar.
rethrow;
// Partial output is kept on failure; native SAF scan resumes from its sidecar.
if (isCancelled?.call() == true) {
throw StateError('Library scan cancelled before native scan');
}
if (forceFullScan) {
// An explicit rescan must not resume metadata from an earlier attempt.
for (final file in [output, File('${output.path}.state')]) {
if (await file.exists()) await file.delete();
}
// Preserve covers referenced by the current DB until ingestion succeeds.
// Fresh paths bypass native disk and Flutter image caches together.
final covers = Directory('${scanDir.path}/library_covers');
await covers.create(recursive: true);
final freshCovers = await covers.createTemp('full_scan_');
await setLibraryCoverCacheDir(freshCovers.path);
}
if (isCancelled?.call() == true) {
throw StateError('Library scan cancelled before native scan');
}
final result = await _channel.invokeMethod(method, {
...arguments,
'output_path': output.path,
});
if (result is! Map) {
throw FormatException('$method returned ${result.runtimeType}');
}
if (result['cancelled'] == true) {
throw FormatException('$method returned a cancelled partial scan');
}
final errors = result['error_count'];
if (errors is! num ||
!errors.isFinite ||
errors < 0 ||
errors != errors.toInt()) {
throw FormatException('$method returned an invalid error count');
}
final pathValue = result['path'];
final countValue = result['count'];
if (pathValue is! String || pathValue.trim().isEmpty) {
throw FormatException('$method returned an invalid output path');
}
if (countValue is! num ||
!countValue.isFinite ||
countValue < 0 ||
countValue != countValue.toInt()) {
throw FormatException('$method returned an invalid row count');
}
final path = pathValue;
final count = countValue.toInt();
final file = File(path);
if (!await file.exists()) {
throw FormatException('$method did not create its output file');
}
return LibraryScanNDJSONFile(
file: file,
expectedCount: count,
errorCount: errors.toInt(),
);
}
static Future<Map<String, dynamic>> scanSafTreeIncremental(