refactor(library): share the scan completion tail as _finishScan

The full-scan and incremental branches of _runScan ended with the same
sequence: source state update, last-scanned prefs, summary refresh, the
mounted check, the final state, log and completion notification. Move
that sequence into _finishScan. The only differences, the cover cache
prune after a full scan and the summary text, become parameters; the
summary stays a closure so it still reads the state after the final
update. Each call is the last statement of its branch, so the early
return on unmount keeps the same effect.
This commit is contained in:
zarzet committed 2026-10-19 01:18:02 +07:00
1 parent b0600c1ff7
commit de142abae6
1 file changed
+72 -92
+72 -92
View File
@@ -1017,52 +1017,14 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
_log.i('Skipped $skippedDownloads files already in download history');
}
final now = DateTime.now();
_sourceVersion++;
await _db.updateSourceState(
activeSourceId,
available: true,
lastSeenAt: now,
lastScannedAt: now,
clearLastScanError: true,
);
try {
final prefs = await SharedPreferences.getInstance();
await writeLocalLibraryLastScannedAt(prefs, now);
await prefs.setInt(_excludedDownloadedCountKey, skippedDownloads);
_log.d('Saved lastScannedAt: $now');
} catch (e) {
_log.w('Failed to save lastScannedAt: $e');
}
await _refreshSummaryFromStorage(
lastScannedAt: now,
excludedDownloadedCount: skippedDownloads,
);
if (!ref.mounted) return;
state = state.copyWith(
isScanning: false,
scanIsFinalizing: false,
scanProgress: 100,
lastScannedAt: now,
scanWasCancelled: false,
excludedDownloadedCount: skippedDownloads,
);
await _pruneLibraryCoverCache();
final summary =
'Full scan complete: ${state.totalCount} tracks found, '
'$skippedDownloads already in downloads, '
'${state.scanErrorCount} errors';
if (state.scanErrorCount > 0) {
_log.e(summary);
} else {
_log.i(summary);
}
await _showScanCompleteNotification(
totalTracks: state.totalCount,
excludedDownloadedCount: skippedDownloads,
errorCount: state.scanErrorCount,
await _finishScan(
sourceId: activeSourceId,
skippedDownloads: skippedDownloads,
pruneCoverCache: true,
summary: () =>
'Full scan complete: ${state.totalCount} tracks found, '
'$skippedDownloads already in downloads, '
'${state.scanErrorCount} errors',
);
} else {
final nativeIngestion = PlatformBridge.supportsCoreBackend;
@@ -1220,52 +1182,15 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
_log.i('Deleted $deleteCount items from database');
}
final now = DateTime.now();
_sourceVersion++;
await _db.updateSourceState(
activeSourceId,
available: true,
lastSeenAt: now,
lastScannedAt: now,
clearLastScanError: true,
);
try {
final prefs = await SharedPreferences.getInstance();
await writeLocalLibraryLastScannedAt(prefs, now);
await prefs.setInt(_excludedDownloadedCountKey, skippedDownloads);
_log.d('Saved lastScannedAt: $now');
} catch (e) {
_log.w('Failed to save lastScannedAt: $e');
}
await _refreshSummaryFromStorage(
lastScannedAt: now,
excludedDownloadedCount: skippedDownloads,
);
if (!ref.mounted) return;
state = state.copyWith(
isScanning: false,
scanIsFinalizing: false,
scanProgress: 100,
lastScannedAt: now,
scanWasCancelled: false,
excludedDownloadedCount: skippedDownloads,
);
final summary =
'Incremental scan complete: ${state.totalCount} total tracks '
'($scannedCount new/updated, $skippedCount unchanged, '
'$deletedCount removed, $skippedDownloads already in downloads, '
'${state.scanErrorCount} errors)';
if (state.scanErrorCount > 0) {
_log.e(summary);
} else {
_log.i(summary);
}
await _showScanCompleteNotification(
totalTracks: state.totalCount,
excludedDownloadedCount: skippedDownloads,
errorCount: state.scanErrorCount,
await _finishScan(
sourceId: activeSourceId,
skippedDownloads: skippedDownloads,
pruneCoverCache: false,
summary: () =>
'Incremental scan complete: ${state.totalCount} total tracks '
'($scannedCount new/updated, $skippedCount unchanged, '
'$deletedCount removed, $skippedDownloads already in downloads, '
'${state.scanErrorCount} errors)',
);
}
} catch (e, stack) {
@@ -1320,6 +1245,61 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
}
}
/// Shared completion tail of a successful full or incremental scan.
/// [summary] is evaluated after the final state update so it reads the
/// refreshed totals.
Future<void> _finishScan({
required String sourceId,
required int skippedDownloads,
required bool pruneCoverCache,
required String Function() summary,
}) async {
final now = DateTime.now();
_sourceVersion++;
await _db.updateSourceState(
sourceId,
available: true,
lastSeenAt: now,
lastScannedAt: now,
clearLastScanError: true,
);
try {
final prefs = await SharedPreferences.getInstance();
await writeLocalLibraryLastScannedAt(prefs, now);
await prefs.setInt(_excludedDownloadedCountKey, skippedDownloads);
_log.d('Saved lastScannedAt: $now');
} catch (e) {
_log.w('Failed to save lastScannedAt: $e');
}
await _refreshSummaryFromStorage(
lastScannedAt: now,
excludedDownloadedCount: skippedDownloads,
);
if (!ref.mounted) return;
state = state.copyWith(
isScanning: false,
scanIsFinalizing: false,
scanProgress: 100,
lastScannedAt: now,
scanWasCancelled: false,
excludedDownloadedCount: skippedDownloads,
);
if (pruneCoverCache) await _pruneLibraryCoverCache();
final message = summary();
if (state.scanErrorCount > 0) {
_log.e(message);
} else {
_log.i(message);
}
await _showScanCompleteNotification(
totalTracks: state.totalCount,
excludedDownloadedCount: skippedDownloads,
errorCount: state.scanErrorCount,
);
}
void _startProgressPolling() {
final useStream = Platform.isAndroid || Platform.isIOS;
_progressPoller.start(useStream: useStream);