@@ -95,8 +95,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
9595 private AtomicBoolean isLoadingComplete ;
9696 /* Has the playlist been modified (e.g. items reordered or deleted) */
9797 private AtomicBoolean isModified ;
98- /* Is the playlist currently being processed to remove watched videos */
99- private boolean isRemovingWatched = false ;
98+ /* Flag to prevent simultaneous rewrites of the playlist */
99+ private boolean isRewritingPlaylist = false ;
100100
101101 public static LocalPlaylistFragment getInstance (final long playlistId , final String name ) {
102102 final LocalPlaylistFragment instance = new LocalPlaylistFragment ();
@@ -353,7 +353,7 @@ public boolean onOptionsItemSelected(final MenuItem item) {
353353 } else if (item .getItemId () == R .id .menu_item_rename_playlist ) {
354354 createRenameDialog ();
355355 } else if (item .getItemId () == R .id .menu_item_remove_watched ) {
356- if (!isRemovingWatched ) {
356+ if (!isRewritingPlaylist ) {
357357 new AlertDialog .Builder (requireContext ())
358358 .setMessage (R .string .remove_watched_popup_warning )
359359 .setTitle (R .string .remove_watched_popup_title )
@@ -368,7 +368,9 @@ public boolean onOptionsItemSelected(final MenuItem item) {
368368 .show ();
369369 }
370370 } else if (item .getItemId () == R .id .menu_item_remove_duplicates ) {
371- openRemoveDuplicatesDialog ();
371+ if (!isRewritingPlaylist ) {
372+ openRemoveDuplicatesDialog ();
373+ }
372374 } else {
373375 return super .onOptionsItemSelected (item );
374376 }
@@ -390,10 +392,10 @@ public void sharePlaylist() {
390392 }
391393
392394 public void removeWatchedStreams (final boolean removePartiallyWatched ) {
393- if (isRemovingWatched ) {
395+ if (isRewritingPlaylist ) {
394396 return ;
395397 }
396- isRemovingWatched = true ;
398+ isRewritingPlaylist = true ;
397399 showLoading ();
398400
399401 final var recordManager = new HistoryRecordManager (getContext ());
@@ -469,7 +471,7 @@ public void removeWatchedStreams(final boolean removePartiallyWatched) {
469471 }
470472
471473 hideLoading ();
472- isRemovingWatched = false ;
474+ isRewritingPlaylist = false ;
473475 }, throwable -> showError (new ErrorInfo (throwable , UserAction .REQUESTED_BOOKMARK ,
474476 "Removing watched videos, partially watched=" + removePartiallyWatched ))));
475477 }
@@ -623,7 +625,6 @@ private void updateThumbnailUrl() {
623625 changeThumbnailUrl (newThumbnailUrl );
624626 }
625627
626-
627628 private void openRemoveDuplicatesDialog () {
628629 final AlertDialog .Builder builder = new AlertDialog .Builder (this .getActivity ());
629630
@@ -638,14 +639,28 @@ private void openRemoveDuplicatesDialog() {
638639 }
639640
640641 private void removeDuplicatesInPlaylist () {
641- final List <PlaylistStreamEntry > itemsToKeep = playlistManager
642- .getDistinctPlaylistStreams (playlistId ).blockingFirst ();
642+ if (isRewritingPlaylist ) {
643+ return ;
644+ }
645+ isRewritingPlaylist = true ;
646+ showLoading ();
643647
644- itemListAdapter .clearStreamItemList ();
645- itemListAdapter .addItems (itemsToKeep );
646- setVideoCount (itemListAdapter .getItemsList ().size ());
648+ final var streamsMaybe = playlistManager
649+ .getDistinctPlaylistStreams (playlistId ).firstElement ();
647650
648- saveChanges ();
651+
652+ disposables .add (streamsMaybe .subscribeOn (Schedulers .io ())
653+ .observeOn (AndroidSchedulers .mainThread ())
654+ .subscribe (itemsToKeep -> {
655+ itemListAdapter .clearStreamItemList ();
656+ itemListAdapter .addItems (itemsToKeep );
657+ setVideoCount (itemListAdapter .getItemsList ().size ());
658+ saveChanges ();
659+
660+ hideLoading ();
661+ isRewritingPlaylist = false ;
662+ }, throwable -> showError (new ErrorInfo (throwable , UserAction .REQUESTED_BOOKMARK ,
663+ "Removing duplicated streams" ))));
649664 }
650665
651666 private void deleteItem (final PlaylistStreamEntry item ) {
0 commit comments