Skip to content
This repository was archived by the owner on Jan 29, 2026. It is now read-only.

Commit 8ce37df

Browse files
authored
Merge pull request #644 from lamarios/feature/allow-download-cancel
fix issues with failed downloads that can't be removed.
2 parents 5343c31 + 8a650da commit 8ce37df

File tree

4 files changed

+91
-45
lines changed

4 files changed

+91
-45
lines changed

lib/downloads/states/download_manager.dart

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ class DownloadManagerCubit extends Cubit<DownloadManagerState> {
8282
var progresses =
8383
Map<String, DownloadProgress>.from(state.downloadProgresses);
8484
var downloadProgress = progresses[video.videoId];
85+
86+
if (downloadProgress == null ||
87+
downloadProgress.cancelToken.isCancelled) {
88+
return;
89+
}
90+
8591
progresses.remove(video.videoId);
8692
video = video.copyWith(downloadComplete: true);
8793
await db.upsertDownload(video);
@@ -167,6 +173,10 @@ class DownloadManagerCubit extends Cubit<DownloadManagerState> {
167173
options: Options(headers: server.headersForUrl(thumbUrl)));
168174
}
169175

176+
if (cancelToken.isCancelled) {
177+
return false;
178+
}
179+
170180
// download video
171181
var mediaPath = await downloadedVideo.downloadPath;
172182

@@ -177,6 +187,9 @@ class DownloadManagerCubit extends Cubit<DownloadManagerState> {
177187
log.info(
178188
"Downloading video ${vid.title}, audioOnly ? $audioOnly, quality: $quality to path: $tempDir");
179189
try {
190+
if (cancelToken.isCancelled) {
191+
return false;
192+
}
180193
await dio
181194
.download(audioUrl, audioPath,
182195
onReceiveProgress: (count, total) => onProgress(
@@ -263,14 +276,14 @@ class DownloadManagerCubit extends Cubit<DownloadManagerState> {
263276
String path = await vid.effectivePath;
264277
await File(path).delete();
265278
} catch (e) {
266-
log.fine('File might not be available, that\'s ok');
279+
log.fine('Video file might not be available, that\'s ok');
267280
}
268281

269282
try {
270283
String path = await vid.thumbnailPath;
271284
await File(path).delete();
272285
} catch (e) {
273-
log.fine('File might not be available, that\'s ok');
286+
log.fine('Thumbnail might not be available, that\'s ok');
274287
}
275288

276289
await db.deleteDownload(vid);

lib/downloads/views/components/downloaded_video.dart

Lines changed: 73 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -25,45 +25,77 @@ class DownloadedVideoView extends StatelessWidget {
2525
return Padding(
2626
padding: const EdgeInsets.symmetric(horizontal: 32.0),
2727
child: Wrap(
28-
alignment: WrapAlignment.center,
29-
runSpacing: 16,
30-
spacing: 16,
31-
children: [
32-
Column(
33-
mainAxisSize: MainAxisSize.min,
34-
children: [
35-
IconButton.filledTonal(
36-
onPressed: () async {
37-
Navigator.of(ctx).pop();
38-
await cubit.copyToDownloadFolder(v);
39-
if (context.mounted) {
40-
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
41-
content:
42-
Text(locals.fileCopiedToDownloadFolder)));
43-
}
44-
},
45-
icon: const Icon(Icons.copy)),
46-
Text(locals.copyToDownloadFolder)
47-
],
48-
),
49-
Column(
50-
mainAxisSize: MainAxisSize.min,
51-
children: [
52-
IconButton.filledTonal(
53-
onPressed: () async {
54-
Navigator.of(ctx).pop();
55-
await cubit.deleteVideo(v);
56-
if (context.mounted) {
57-
ScaffoldMessenger.of(context).showSnackBar(
58-
SnackBar(content: Text(locals.videoDeleted)));
59-
}
60-
},
61-
icon: const Icon(Icons.delete)),
62-
Text(locals.delete)
63-
],
64-
)
65-
],
66-
),
28+
alignment: WrapAlignment.center,
29+
runSpacing: 16,
30+
spacing: 16,
31+
children: [
32+
if (!v.downloadFailed && !v.downloadComplete)
33+
Column(
34+
mainAxisSize: MainAxisSize.min,
35+
children: [
36+
IconButton.filledTonal(
37+
onPressed: () async {
38+
Navigator.of(ctx).pop();
39+
await cubit.deleteVideo(v);
40+
if (context.mounted) {
41+
ScaffoldMessenger.of(context).showSnackBar(
42+
SnackBar(content: Text(locals.videoDeleted)));
43+
}
44+
},
45+
icon: const Icon(Icons.clear)),
46+
Text(locals.cancel)
47+
],
48+
),
49+
if (v.downloadComplete)
50+
Column(
51+
mainAxisSize: MainAxisSize.min,
52+
children: [
53+
IconButton.filledTonal(
54+
onPressed: () async {
55+
Navigator.of(ctx).pop();
56+
await cubit.copyToDownloadFolder(v);
57+
if (context.mounted) {
58+
ScaffoldMessenger.of(context).showSnackBar(
59+
SnackBar(
60+
content: Text(
61+
locals.fileCopiedToDownloadFolder)));
62+
}
63+
},
64+
icon: const Icon(Icons.copy)),
65+
Text(locals.copyToDownloadFolder)
66+
],
67+
),
68+
if (v.downloadFailed)
69+
Column(
70+
mainAxisSize: MainAxisSize.min,
71+
children: [
72+
IconButton.filledTonal(
73+
onPressed: () async {
74+
Navigator.of(ctx).pop();
75+
await cubit.retryDownload(v);
76+
},
77+
icon: const Icon(Icons.refresh)),
78+
Text(locals.retry)
79+
],
80+
),
81+
if (v.downloadComplete || v.downloadFailed)
82+
Column(
83+
mainAxisSize: MainAxisSize.min,
84+
children: [
85+
IconButton.filledTonal(
86+
onPressed: () async {
87+
Navigator.of(ctx).pop();
88+
await cubit.deleteVideo(v);
89+
if (context.mounted) {
90+
ScaffoldMessenger.of(context).showSnackBar(
91+
SnackBar(content: Text(locals.videoDeleted)));
92+
}
93+
},
94+
icon: const Icon(Icons.delete)),
95+
Text(locals.delete)
96+
],
97+
)
98+
]),
6799
);
68100
},
69101
);
@@ -93,8 +125,8 @@ class DownloadedVideoView extends StatelessWidget {
93125
duration: animationDuration,
94126
child: CompactVideo(
95127
offlineVideo: state.video,
96-
onTap: downloadFailed
97-
? cubit.retryDownload
128+
onTap: downloadFailed || !state.video!.downloadComplete
129+
? () => openVideoSheet(context, state.video!)
98130
: cubit.playVideo,
99131
trailing: [
100132
(state.video?.audioOnly ?? false)

lib/l10n/app_en.arb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1382,5 +1382,6 @@
13821382
"cancelSleepTimer": "Cancel sleep timer",
13831383
"premieresIn": "Premieres in {formattedDuration}",
13841384
"screenControls": "Screen controls",
1385-
"screenControlsExplanation": "When watching a video in full screen, Vertically dragging from the left or the right will adjust the brightness or volume respectively"
1385+
"screenControlsExplanation": "When watching a video in full screen, Vertically dragging from the left or the right will adjust the brightness or volume respectively",
1386+
"retry": "Retry"
13861387
}

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: clipious
2-
version: 1.22.3+4066
2+
version: 1.22.4+4067
33
publish_to: none
44
description: Client for invidious.
55
environment:

0 commit comments

Comments
 (0)