fix: resume interrupted downloads after force-kill
This commit is contained in:
+7
-1
@@ -214,7 +214,7 @@ class _MainAppState extends State<MainApp> with WidgetsBindingObserver {
|
||||
PlexApiCache.initialize(_appDatabase);
|
||||
|
||||
_downloadManager = DownloadManagerService(database: _appDatabase, storageService: DownloadStorageService.instance);
|
||||
_downloadManager.recoverInterruptedDownloads();
|
||||
_downloadManager.recoveryFuture = _downloadManager.recoverInterruptedDownloads();
|
||||
|
||||
_offlineWatchSyncService = OfflineWatchSyncService(database: _appDatabase, serverManager: _serverManager);
|
||||
|
||||
@@ -398,6 +398,12 @@ class _SetupScreenState extends State<SetupScreen> {
|
||||
if (!mounted) return;
|
||||
|
||||
if (result.hasConnections) {
|
||||
// Resume any downloads that were interrupted by app kill
|
||||
final downloadProvider = context.read<DownloadProvider>();
|
||||
downloadProvider.ensureInitialized().then((_) {
|
||||
downloadProvider.resumeQueuedDownloads(result.firstClient!);
|
||||
});
|
||||
|
||||
Navigator.pushReplacement(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => MainScreen(client: result.firstClient!)),
|
||||
|
||||
@@ -71,6 +71,10 @@ class DownloadProvider extends ChangeNotifier {
|
||||
/// Load all persisted downloads and metadata from the database/cache
|
||||
Future<void> _loadPersistedDownloads() async {
|
||||
try {
|
||||
// Wait for recovery to finish before loading state so that
|
||||
// interrupted "downloading" rows have been transitioned to "queued"
|
||||
await _downloadManager.recoveryFuture;
|
||||
|
||||
// Clear existing data to prevent stale entries after deletions
|
||||
_downloads.clear();
|
||||
_artworkPaths.clear();
|
||||
@@ -987,6 +991,12 @@ class DownloadProvider extends ChangeNotifier {
|
||||
await _loadPersistedDownloads();
|
||||
}
|
||||
|
||||
/// Resume queued downloads that were interrupted by app kill.
|
||||
/// Call after a PlexClient becomes available (e.g. after server connect on launch).
|
||||
void resumeQueuedDownloads(PlexClient client) {
|
||||
_downloadManager.resumeQueuedDownloads(client);
|
||||
}
|
||||
|
||||
/// Refresh only metadata from API cache (after watch state sync).
|
||||
///
|
||||
/// This is more lightweight than full refresh() - only updates metadata
|
||||
|
||||
@@ -244,6 +244,10 @@ class DownloadManagerService {
|
||||
!connectivity.contains(ConnectivityResult.ethernet);
|
||||
}
|
||||
|
||||
/// Future that completes when interrupted download recovery finishes.
|
||||
/// Await this before reading download state from the DB to avoid races.
|
||||
late final Future<void> recoveryFuture;
|
||||
|
||||
DownloadManagerService({required AppDatabase database, required DownloadStorageService storageService, Dio? dio})
|
||||
: _database = database,
|
||||
_storageService = storageService,
|
||||
@@ -271,6 +275,17 @@ class DownloadManagerService {
|
||||
}
|
||||
}
|
||||
|
||||
/// Resume queued downloads that have no active processing.
|
||||
/// Call after a PlexClient becomes available (e.g. after server connect on launch).
|
||||
void resumeQueuedDownloads(PlexClient client) {
|
||||
_database.getNextQueueItem().then((item) {
|
||||
if (item != null && !_isProcessingQueue) {
|
||||
appLogger.i('Resuming queued downloads after app restart');
|
||||
_processQueue(client);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Delete a file if it exists and log the deletion
|
||||
/// Returns true if file was deleted, false otherwise
|
||||
Future<bool> _deleteFileIfExists(File file, String description) async {
|
||||
|
||||
Reference in New Issue
Block a user