From eb3363d4dd76a69a14777390023c159f42daf2dc Mon Sep 17 00:00:00 2001 From: Jared Fantaye Date: Tue, 10 Jan 2023 20:55:18 +0100 Subject: [PATCH 1/7] Created the first draft. --- .../playlist/dao/PlaylistStreamDAO.java | 11 ++++++++++ .../local/playlist/LocalPlaylistFragment.java | 20 +++++++++++++++++++ .../local/playlist/LocalPlaylistManager.java | 6 ++++++ app/src/main/res/menu/menu_local_playlist.xml | 6 ++++++ app/src/main/res/values/strings.xml | 1 + 5 files changed, 44 insertions(+) diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java index 4941d9395..594df5c25 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java @@ -83,4 +83,15 @@ public interface PlaylistStreamDAO extends BasicDAO { + " GROUP BY " + JOIN_PLAYLIST_ID + " ORDER BY " + PLAYLIST_NAME + " COLLATE NOCASE ASC") Flowable> getPlaylistMetadata(); + + @Transaction + @Query("DELETE FROM " + PLAYLIST_STREAM_JOIN_TABLE + + " WHERE " + JOIN_PLAYLIST_ID + "=:playlistId" + + " AND " + JOIN_STREAM_ID + " IN (" + + " SELECT " + JOIN_STREAM_ID + + " FROM " + PLAYLIST_STREAM_JOIN_TABLE + + " WHERE " + JOIN_PLAYLIST_ID + "=:playlistId" + + " GROUP BY " + JOIN_STREAM_ID + + " HAVING COUNT(*) > 1 )" ) + Flowable> removeDuplicates(long playlistId); } diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index d98ce4121..a5fb67576 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -367,6 +367,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment { + removeDuplicatesInPlaylist(); + }) + .setNeutralButton(R.string.cancel, null); + + builder.create().show(); + } + + private void removeDuplicatesInPlaylist() { + + } + private void deleteItem(final PlaylistStreamEntry item) { if (itemListAdapter == null) { return; diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java index 33296aa84..0752ab49d 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java @@ -86,6 +86,12 @@ public class LocalPlaylistManager { return playlistStreamTable.getPlaylistMetadata().subscribeOn(Schedulers.io()); } + public Flowable> removeDuplicateStreams() { + // TODO: Delete Duplicates and rebuild the index + // TODO: Rebuild the index + return playlistStreamTable.getPlaylistMetadata().subscribeOn(Schedulers.io()); + } + public Flowable> getPlaylistStreams(final long playlistId) { return playlistStreamTable.getOrderedStreamsOf(playlistId).subscribeOn(Schedulers.io()); } diff --git a/app/src/main/res/menu/menu_local_playlist.xml b/app/src/main/res/menu/menu_local_playlist.xml index 0ff182b48..c57e8ad95 100644 --- a/app/src/main/res/menu/menu_local_playlist.xml +++ b/app/src/main/res/menu/menu_local_playlist.xml @@ -12,8 +12,14 @@ android:id="@+id/menu_item_rename_playlist" android:title="@string/rename_playlist" app:showAsAction="never" /> + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4e6889304..5d8ddb692 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -626,6 +626,7 @@ System default Remove watched Remove watched videos? + Remove duplicates Videos that have been watched before and after being added to the playlist will be removed. \nAre you sure\? This cannot be undone! Yes, and partially watched videos From 135fc082126529c0cc0dea2e3128d9fbaa86890a Mon Sep 17 00:00:00 2001 From: Jared Fantaye Date: Fri, 13 Jan 2023 21:35:22 +0100 Subject: [PATCH 2/7] Implemented the "remove duplicates" feature. --- .../playlist/dao/PlaylistStreamDAO.java | 24 ++++++++++++------- .../local/playlist/LocalPlaylistFragment.java | 17 +++++++++++-- .../local/playlist/LocalPlaylistManager.java | 7 +++--- app/src/main/res/values/strings.xml | 2 ++ 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java index 594df5c25..015a77002 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java @@ -84,14 +84,22 @@ public interface PlaylistStreamDAO extends BasicDAO { + " ORDER BY " + PLAYLIST_NAME + " COLLATE NOCASE ASC") Flowable> getPlaylistMetadata(); + @RewriteQueriesToDropUnusedColumns @Transaction - @Query("DELETE FROM " + PLAYLIST_STREAM_JOIN_TABLE - + " WHERE " + JOIN_PLAYLIST_ID + "=:playlistId" - + " AND " + JOIN_STREAM_ID + " IN (" - + " SELECT " + JOIN_STREAM_ID + @Query("SELECT *, MIN(" + JOIN_INDEX + ") FROM " + STREAM_TABLE + " INNER JOIN " + + "(SELECT " + JOIN_STREAM_ID + "," + JOIN_INDEX + " FROM " + PLAYLIST_STREAM_JOIN_TABLE - + " WHERE " + JOIN_PLAYLIST_ID + "=:playlistId" - + " GROUP BY " + JOIN_STREAM_ID - + " HAVING COUNT(*) > 1 )" ) - Flowable> removeDuplicates(long playlistId); + + " WHERE " + JOIN_PLAYLIST_ID + " = :playlistId)" + + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID + + " LEFT JOIN " + + "(SELECT " + JOIN_STREAM_ID + " AS " + JOIN_STREAM_ID_ALIAS + ", " + + STREAM_PROGRESS_MILLIS + + " FROM " + STREAM_STATE_TABLE + " )" + + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID_ALIAS + + " GROUP BY " + STREAM_ID + + " ORDER BY " + JOIN_INDEX + " ASC") + Flowable> getStreamsWithoutDuplicates(long playlistId); + + + } diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index a5fb67576..9881a0a20 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -627,8 +627,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment { removeDuplicatesInPlaylist(); }) @@ -638,7 +638,20 @@ public class LocalPlaylistFragment extends BaseLocalListFragment itemsToKeep = playlistManager + .getDistinctPlaylistStreams(playlistId).blockingFirst(); + itemListAdapter.clearStreamItemList(); + itemListAdapter.addItems(itemsToKeep); + saveChanges(); + + final long videoCount = itemListAdapter.getItemsList().size(); + setVideoCount(videoCount); + if (videoCount == 0) { + showEmptyState(); + } + //TODO: Do we have to show loading? + //hideLoading(); } private void deleteItem(final PlaylistStreamEntry item) { diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java index 0752ab49d..f397be0df 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistManager.java @@ -86,10 +86,9 @@ public class LocalPlaylistManager { return playlistStreamTable.getPlaylistMetadata().subscribeOn(Schedulers.io()); } - public Flowable> removeDuplicateStreams() { - // TODO: Delete Duplicates and rebuild the index - // TODO: Rebuild the index - return playlistStreamTable.getPlaylistMetadata().subscribeOn(Schedulers.io()); + public Flowable> getDistinctPlaylistStreams(final long playlistId) { + return playlistStreamTable + .getStreamsWithoutDuplicates(playlistId).subscribeOn(Schedulers.io()); } public Flowable> getPlaylistStreams(final long playlistId) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5d8ddb692..cdde2e5ee 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -627,6 +627,8 @@ Remove watched Remove watched videos? Remove duplicates + Remove duplicates? + Do you want to remove all duplicate streams in this playlist? Videos that have been watched before and after being added to the playlist will be removed. \nAre you sure\? This cannot be undone! Yes, and partially watched videos From e26c03856589c1552ee5ec98a31b6b8ef5c1274a Mon Sep 17 00:00:00 2001 From: Jared Fantaye Date: Fri, 20 Jan 2023 11:55:50 +0100 Subject: [PATCH 3/7] Made some small adjustments --- .../newpipe/local/playlist/LocalPlaylistFragment.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 9881a0a20..36544a6a9 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -643,15 +643,9 @@ public class LocalPlaylistFragment extends BaseLocalListFragment Date: Thu, 9 Feb 2023 20:41:22 +0100 Subject: [PATCH 4/7] Made some small adjustments to the database query --- .../newpipe/database/playlist/dao/PlaylistStreamDAO.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java index 015a77002..54fa2d53b 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java @@ -86,8 +86,9 @@ public interface PlaylistStreamDAO extends BasicDAO { @RewriteQueriesToDropUnusedColumns @Transaction - @Query("SELECT *, MIN(" + JOIN_INDEX + ") FROM " + STREAM_TABLE + " INNER JOIN " - + "(SELECT " + JOIN_STREAM_ID + "," + JOIN_INDEX + @Query("SELECT *, MIN(" + JOIN_INDEX + ")" + + " FROM " + STREAM_TABLE + " INNER JOIN" + + " (SELECT " + JOIN_STREAM_ID + "," + JOIN_INDEX + " FROM " + PLAYLIST_STREAM_JOIN_TABLE + " WHERE " + JOIN_PLAYLIST_ID + " = :playlistId)" + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID @@ -97,7 +98,7 @@ public interface PlaylistStreamDAO extends BasicDAO { + " FROM " + STREAM_STATE_TABLE + " )" + " ON " + STREAM_ID + " = " + JOIN_STREAM_ID_ALIAS + " GROUP BY " + STREAM_ID - + " ORDER BY " + JOIN_INDEX + " ASC") + + " ORDER BY MIN(" + JOIN_INDEX + ") ASC") Flowable> getStreamsWithoutDuplicates(long playlistId); From d8ed2c850356de9c1aa1e4b3596745983b3d5344 Mon Sep 17 00:00:00 2001 From: Jared Fantaye Date: Tue, 28 Feb 2023 16:43:58 +0100 Subject: [PATCH 5/7] Refactoring removeDuplicates function and preventing concurrent calls. --- .../local/playlist/LocalPlaylistFragment.java | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 36544a6a9..63cc1b57c 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -95,8 +95,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment showError(new ErrorInfo(throwable, UserAction.REQUESTED_BOOKMARK, "Removing watched videos, partially watched=" + removePartiallyWatched)))); } @@ -623,7 +625,6 @@ public class LocalPlaylistFragment extends BaseLocalListFragment itemsToKeep = playlistManager - .getDistinctPlaylistStreams(playlistId).blockingFirst(); + if (isRewritingPlaylist) { + return; + } + isRewritingPlaylist = true; + showLoading(); - itemListAdapter.clearStreamItemList(); - itemListAdapter.addItems(itemsToKeep); - setVideoCount(itemListAdapter.getItemsList().size()); + final var streamsMaybe = playlistManager + .getDistinctPlaylistStreams(playlistId).firstElement(); - saveChanges(); + + disposables.add(streamsMaybe.subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(itemsToKeep -> { + itemListAdapter.clearStreamItemList(); + itemListAdapter.addItems(itemsToKeep); + setVideoCount(itemListAdapter.getItemsList().size()); + saveChanges(); + + hideLoading(); + isRewritingPlaylist = false; + }, throwable -> showError(new ErrorInfo(throwable, UserAction.REQUESTED_BOOKMARK, + "Removing duplicated streams")))); } private void deleteItem(final PlaylistStreamEntry item) { From 7617f8cdc71d42287b0ee7772234d86c49fe17e3 Mon Sep 17 00:00:00 2001 From: Stypox Date: Tue, 28 Feb 2023 21:35:57 +0100 Subject: [PATCH 6/7] Update app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java --- .../schabi/newpipe/local/playlist/LocalPlaylistFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index ef76fe8e9..8a71ce3a8 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -637,7 +637,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment { + .setPositiveButton(R.string.ok, (dialog, i) -> { removeDuplicatesInPlaylist(); }) .setNeutralButton(R.string.cancel, null); From 43f46e29ad24910d5b7700bc2f6be56c326336cc Mon Sep 17 00:00:00 2001 From: Stypox Date: Tue, 28 Feb 2023 21:40:11 +0100 Subject: [PATCH 7/7] Update app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java --- .../schabi/newpipe/local/playlist/LocalPlaylistFragment.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 8a71ce3a8..1da211b80 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -637,9 +637,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment { - removeDuplicatesInPlaylist(); - }) + .setPositiveButton(R.string.ok, + (dialog, i) -> removeDuplicatesInPlaylist()) .setNeutralButton(R.string.cancel, null); builder.create().show();