Skip to content

feat: implement "Resume All" functionality for downloads#8165

Open
bermount wants to merge 2 commits intolibre-tube:masterfrom
bermount:resume-download
Open

feat: implement "Resume All" functionality for downloads#8165
bermount wants to merge 2 commits intolibre-tube:masterfrom
bermount:resume-download

Conversation

@bermount
Copy link
Contributor

@bermount bermount commented Feb 7, 2026

Adds a "Resume All" button to the downloads screen that allows users to simultaneously resume all incomplete downloads. This is managed by tracking incomplete download IDs in preferences and implementing a new service action that fills available download slots up to the maximum concurrence limit. The button is hidden when there is no incomplete download.
Works with #8161 .

Adds a "Resume All" button to the downloads screen that allows users to
simultaneously resume all incomplete downloads. This is managed by
tracking incomplete download IDs in preferences and implementing a new
service action that fills available download slots up to the maximum
concurrence limit.
Ensure that the download ID is tracked when manually resuming downloads.
app:layout_constraintBottom_toTopOf="@+id/delete_all"
app:layout_constraintEnd_toEndOf="parent"
tools:targetApi="o"
tools:visibility="visible" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally think that this button is a bit unintuitive, i.e. the logo is just a download button and not really self-explainable.

Instead, I think it would look better to put the button in the same line as the sort order button.

I know this conflicts with the playlist name, but I think it's still the better solution. E.g. this could look like the following (tested locally):

diff --git a/app/src/main/java/com/github/libretube/ui/fragments/DownloadsFragment.kt b/app/src/main/java/com/github/libretube/ui/fragments/DownloadsFragment.kt
index 47123b199..fc38bbc78 100644
--- a/app/src/main/java/com/github/libretube/ui/fragments/DownloadsFragment.kt
+++ b/app/src/main/java/com/github/libretube/ui/fragments/DownloadsFragment.kt
@@ -231,6 +231,7 @@ class DownloadsFragmentPage : DynamicLayoutManagerFragment(R.layout.fragment_dow
                 }
 
                 binding.playlistName.text = playlist.downloadPlaylist.title
+                binding.playlistName.isVisible = true
 
                 playlist.downloadVideos.map { it.videoId }
             }
diff --git a/app/src/main/res/layout/fragment_download_content.xml b/app/src/main/res/layout/fragment_download_content.xml
index 151e3b0cf..bcb36d962 100644
--- a/app/src/main/res/layout/fragment_download_content.xml
+++ b/app/src/main/res/layout/fragment_download_content.xml
@@ -12,44 +12,64 @@
         android:layout_height="match_parent"
         android:orientation="vertical">
 
-        <LinearLayout
+        <RelativeLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="horizontal">
+            android:paddingHorizontal="8dp">
 
-            <TextView
-                android:id="@+id/playlist_name"
-                android:layout_width="0dp"
-                android:layout_weight="1"
+            <com.google.android.material.button.MaterialButton
+                android:id="@+id/resume_all"
+                android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:maxLines="1"
-                android:textSize="18sp"
-                android:textStyle="bold"
-                android:ellipsize="end"
-                android:paddingHorizontal="8dp"
-                tools:text="Downloaded Playlist Name"/>
+                android:text="@string/resume_all"
+                android:contentDescription="@string/resume_all"
+                app:icon="@drawable/ic_play"
+                android:tooltipText="@string/resume_all"
+                android:visibility="gone"
+                tools:targetApi="o"
+                tools:visibility="visible" />
 
             <com.google.android.material.button.MaterialButton
                 android:id="@+id/sort_type"
                 style="?materialButtonTonalStyle"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-            android:layout_marginEnd="8dp"
-            android:ellipsize="end"
+                android:layout_marginEnd="8dp"
+                android:ellipsize="end"
                 android:maxLines="1"
                 android:paddingHorizontal="10dp"
+                android:layout_alignParentEnd="true"
                 android:text="@string/sort_by"
                 app:icon="@drawable/ic_sort"
+                android:gravity="end"
                 app:iconGravity="textEnd" />
 
-        </LinearLayout>
+        </RelativeLayout>
+
+        <TextView
+            android:id="@+id/playlist_name"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:maxLines="1"
+            android:textSize="18sp"
+            android:textStyle="bold"
+            android:ellipsize="end"
+            android:paddingHorizontal="8dp"
+            android:visibility="gone"
+            tools:visibility="visible"
+            tools:text="Downloaded Playlist Name"/>
 
         <androidx.recyclerview.widget.RecyclerView
             android:id="@+id/downloads_recView"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
-            android:orientation="vertical"/>
+            android:orientation="vertical" />
+
+        <androidx.fragment.app.FragmentContainerView
+            android:id="@+id/fragment"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent" />
 
     </LinearLayout>
 
@@ -78,23 +98,6 @@
             android:textStyle="bold" />
     </LinearLayout>
 
-    <com.google.android.material.floatingactionbutton.FloatingActionButton
-        android:id="@+id/resume_all"
-        style="?attr/floatingActionButtonSmallSecondaryStyle"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="end"
-        android:layout_marginEnd="16dp"
-        android:layout_marginBottom="8dp"
-        android:contentDescription="@string/resume"
-        android:src="@drawable/ic_download"
-        android:tooltipText="@string/resume"
-        android:visibility="gone"
-        app:layout_constraintBottom_toTopOf="@+id/delete_all"
-        app:layout_constraintEnd_toEndOf="parent"
-        tools:targetApi="o"
-        tools:visibility="visible" />
-
     <com.google.android.material.floatingactionbutton.FloatingActionButton
         android:id="@+id/delete_all"
         style="?attr/floatingActionButtonSmallSecondaryStyle"
@@ -127,9 +130,4 @@
         tools:targetApi="o"
         tools:visibility="visible" />
 
-    <androidx.fragment.app.FragmentContainerView
-        android:id="@+id/fragment"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0c6fb58cc..1f5ac9cce 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -543,6 +543,7 @@
     <string name="include_timestamp_in_filename">Include timestamp in filename</string>
     <string name="did_you_mean">Did you mean:</string>
     <string name="showing_results_for">Showing results for:</string>
+    <string name="resume_all">Resume all</string>
 
     <!-- Notification channel strings -->
     <string name="download_channel_name">Download Service</string>

private fun resumeAll() {
lifecycleScope.launch(coroutineContext) {
// Get incomplete items directly using stored IDs
val incompleteIds = DownloadHelper.getIncompleteDownloadIds()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of storing the incomplete download IDs in the preferences, can't we just iterate over all download items in the database and compare their downloadSize to the actual file size?

Or otherwise we should store an isFinished attribute in the DownloadItem table, instead of putting that information into the preferences store.

@Bnyro
Copy link
Member

Bnyro commented Feb 19, 2026

Very good idea, thanks for the PR 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants