diff --git a/lib/downloads/states/download_manager.dart b/lib/downloads/states/download_manager.dart index 6a00309d..f4be55f5 100644 --- a/lib/downloads/states/download_manager.dart +++ b/lib/downloads/states/download_manager.dart @@ -82,6 +82,12 @@ class DownloadManagerCubit extends Cubit { var progresses = Map.from(state.downloadProgresses); var downloadProgress = progresses[video.videoId]; + + if (downloadProgress == null || + downloadProgress.cancelToken.isCancelled) { + return; + } + progresses.remove(video.videoId); video = video.copyWith(downloadComplete: true); await db.upsertDownload(video); @@ -167,6 +173,10 @@ class DownloadManagerCubit extends Cubit { options: Options(headers: server.headersForUrl(thumbUrl))); } + if (cancelToken.isCancelled) { + return false; + } + // download video var mediaPath = await downloadedVideo.downloadPath; @@ -177,6 +187,9 @@ class DownloadManagerCubit extends Cubit { log.info( "Downloading video ${vid.title}, audioOnly ? $audioOnly, quality: $quality to path: $tempDir"); try { + if (cancelToken.isCancelled) { + return false; + } await dio .download(audioUrl, audioPath, onReceiveProgress: (count, total) => onProgress( @@ -263,14 +276,14 @@ class DownloadManagerCubit extends Cubit { String path = await vid.effectivePath; await File(path).delete(); } catch (e) { - log.fine('File might not be available, that\'s ok'); + log.fine('Video file might not be available, that\'s ok'); } try { String path = await vid.thumbnailPath; await File(path).delete(); } catch (e) { - log.fine('File might not be available, that\'s ok'); + log.fine('Thumbnail might not be available, that\'s ok'); } await db.deleteDownload(vid); diff --git a/lib/downloads/views/components/downloaded_video.dart b/lib/downloads/views/components/downloaded_video.dart index b187831a..83a79385 100644 --- a/lib/downloads/views/components/downloaded_video.dart +++ b/lib/downloads/views/components/downloaded_video.dart @@ -25,45 +25,77 @@ class DownloadedVideoView extends StatelessWidget { return Padding( padding: const EdgeInsets.symmetric(horizontal: 32.0), child: Wrap( - alignment: WrapAlignment.center, - runSpacing: 16, - spacing: 16, - children: [ - Column( - mainAxisSize: MainAxisSize.min, - children: [ - IconButton.filledTonal( - onPressed: () async { - Navigator.of(ctx).pop(); - await cubit.copyToDownloadFolder(v); - if (context.mounted) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: - Text(locals.fileCopiedToDownloadFolder))); - } - }, - icon: const Icon(Icons.copy)), - Text(locals.copyToDownloadFolder) - ], - ), - Column( - mainAxisSize: MainAxisSize.min, - children: [ - IconButton.filledTonal( - onPressed: () async { - Navigator.of(ctx).pop(); - await cubit.deleteVideo(v); - if (context.mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text(locals.videoDeleted))); - } - }, - icon: const Icon(Icons.delete)), - Text(locals.delete) - ], - ) - ], - ), + alignment: WrapAlignment.center, + runSpacing: 16, + spacing: 16, + children: [ + if (!v.downloadFailed && !v.downloadComplete) + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton.filledTonal( + onPressed: () async { + Navigator.of(ctx).pop(); + await cubit.deleteVideo(v); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(locals.videoDeleted))); + } + }, + icon: const Icon(Icons.clear)), + Text(locals.cancel) + ], + ), + if (v.downloadComplete) + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton.filledTonal( + onPressed: () async { + Navigator.of(ctx).pop(); + await cubit.copyToDownloadFolder(v); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + locals.fileCopiedToDownloadFolder))); + } + }, + icon: const Icon(Icons.copy)), + Text(locals.copyToDownloadFolder) + ], + ), + if (v.downloadFailed) + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton.filledTonal( + onPressed: () async { + Navigator.of(ctx).pop(); + await cubit.retryDownload(v); + }, + icon: const Icon(Icons.refresh)), + Text(locals.retry) + ], + ), + if (v.downloadComplete || v.downloadFailed) + Column( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton.filledTonal( + onPressed: () async { + Navigator.of(ctx).pop(); + await cubit.deleteVideo(v); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(locals.videoDeleted))); + } + }, + icon: const Icon(Icons.delete)), + Text(locals.delete) + ], + ) + ]), ); }, ); @@ -93,8 +125,8 @@ class DownloadedVideoView extends StatelessWidget { duration: animationDuration, child: CompactVideo( offlineVideo: state.video, - onTap: downloadFailed - ? cubit.retryDownload + onTap: downloadFailed || !state.video!.downloadComplete + ? () => openVideoSheet(context, state.video!) : cubit.playVideo, trailing: [ (state.video?.audioOnly ?? false) diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index fa170541..1914ba19 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -1382,5 +1382,6 @@ "cancelSleepTimer": "Cancel sleep timer", "premieresIn": "Premieres in {formattedDuration}", "screenControls": "Screen controls", - "screenControlsExplanation": "When watching a video in full screen, Vertically dragging from the left or the right will adjust the brightness or volume respectively" + "screenControlsExplanation": "When watching a video in full screen, Vertically dragging from the left or the right will adjust the brightness or volume respectively", + "retry": "Retry" } diff --git a/pubspec.yaml b/pubspec.yaml index 9a289403..be862253 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: clipious -version: 1.22.3+4066 +version: 1.22.4+4067 publish_to: none description: Client for invidious. environment: