Skip to content

Commit bb5390d

Browse files
committed
Reuse DebounceSaver
1 parent bd1aae8 commit bb5390d

5 files changed

Lines changed: 142 additions & 103 deletions

File tree

app/src/main/java/org/schabi/newpipe/database/playlist/PlaylistLocalItem.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ static List<PlaylistLocalItem> merge(
1717
final List<PlaylistMetadataEntry> localPlaylists,
1818
final List<PlaylistRemoteEntity> remotePlaylists) {
1919

20-
// Merge localPlaylists and remotePlaylists by displayIndex.
21-
// If two items have the same displayIndex, sort them in CASE_INSENSITIVE_ORDER.
20+
// Merge localPlaylists and remotePlaylists by display index.
21+
// If two items have the same display index, sort them in CASE_INSENSITIVE_ORDER.
2222
// This algorithm is similar to the merge operation in merge sort.
2323

2424
final List<PlaylistLocalItem> result = new ArrayList<>(
2525
localPlaylists.size() + remotePlaylists.size());
2626
final List<PlaylistLocalItem> itemsWithSameIndex = new ArrayList<>();
2727

28-
// The data from database may not be in the displayIndex order
28+
// The data from database may not be in the display index order
2929
Collections.sort(localPlaylists,
3030
Comparator.comparingLong(PlaylistMetadataEntry::getDisplayIndex));
3131
Collections.sort(remotePlaylists,
@@ -58,7 +58,7 @@ static void addItem(final List<PlaylistLocalItem> result, final PlaylistLocalIte
5858
final List<PlaylistLocalItem> itemsWithSameIndex) {
5959
if (!itemsWithSameIndex.isEmpty()
6060
&& itemsWithSameIndex.get(0).getDisplayIndex() != item.getDisplayIndex()) {
61-
// The new item has a different displayIndex, add previous items with same
61+
// The new item has a different display index, add previous items with same
6262
// index to the result.
6363
addItemsWithSameIndex(result, itemsWithSameIndex);
6464
itemsWithSameIndex.clear();

app/src/main/java/org/schabi/newpipe/local/bookmark/BookmarkFragment.java

Lines changed: 29 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,26 @@
3535
import org.schabi.newpipe.local.holder.RemoteBookmarkPlaylistItemHolder;
3636
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
3737
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
38+
import org.schabi.newpipe.util.DebounceSavable;
39+
import org.schabi.newpipe.util.DebounceSaver;
3840
import org.schabi.newpipe.util.NavigationHelper;
3941
import org.schabi.newpipe.util.OnClickGesture;
4042

4143
import java.util.ArrayList;
4244
import java.util.HashMap;
4345
import java.util.List;
4446
import java.util.Map;
45-
import java.util.concurrent.TimeUnit;
4647
import java.util.concurrent.atomic.AtomicBoolean;
4748

4849
import icepick.State;
4950
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
5051
import io.reactivex.rxjava3.core.Flowable;
5152
import io.reactivex.rxjava3.disposables.CompositeDisposable;
5253
import io.reactivex.rxjava3.disposables.Disposable;
53-
import io.reactivex.rxjava3.subjects.PublishSubject;
5454

55-
public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistLocalItem>, Void> {
55+
public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistLocalItem>, Void>
56+
implements DebounceSavable {
5657

57-
// Save the list 10 seconds after the last change occurred
58-
private static final long SAVE_DEBOUNCE_MILLIS = 10000;
5958
private static final int MINIMUM_INITIAL_DRAG_VELOCITY = 12;
6059
@State
6160
protected Parcelable itemsListState;
@@ -66,12 +65,10 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
6665
private RemotePlaylistManager remotePlaylistManager;
6766
private ItemTouchHelper itemTouchHelper;
6867

69-
private PublishSubject<Long> debouncedSaveSignal;
70-
71-
/* Has the playlist been fully loaded from db */
68+
/* Have the bookmarked playlists been fully loaded from db */
7269
private AtomicBoolean isLoadingComplete;
73-
/* Has the playlist been modified (e.g. items reordered or deleted) */
74-
private AtomicBoolean isModified;
70+
71+
private DebounceSaver debounceSaver;
7572

7673
// Map from (uid, local/remote item) to the saved display index in the database.
7774
private Map<Pair<Long, LocalItem.LocalItemType>, Long> displayIndexInDatabase;
@@ -91,9 +88,8 @@ public void onCreate(final Bundle savedInstanceState) {
9188
remotePlaylistManager = new RemotePlaylistManager(database);
9289
disposables = new CompositeDisposable();
9390

94-
debouncedSaveSignal = PublishSubject.create();
9591
isLoadingComplete = new AtomicBoolean();
96-
isModified = new AtomicBoolean();
92+
debounceSaver = new DebounceSaver(10000, this);
9793

9894
displayIndexInDatabase = new HashMap<>();
9995
}
@@ -183,9 +179,11 @@ public void drag(final LocalItem selectedItem,
183179
public void startLoading(final boolean forceLoad) {
184180
super.startLoading(forceLoad);
185181

186-
disposables.add(getDebouncedSaver());
182+
if (debounceSaver != null) {
183+
disposables.add(debounceSaver.getDebouncedSaver());
184+
debounceSaver.setIsModified(false);
185+
}
187186
isLoadingComplete.set(false);
188-
isModified.set(false);
189187

190188
Flowable.combineLatest(localPlaylistManager.getPlaylists(),
191189
remotePlaylistManager.getPlaylists(), PlaylistLocalItem::merge)
@@ -225,21 +223,20 @@ public void onDestroyView() {
225223
@Override
226224
public void onDestroy() {
227225
super.onDestroy();
228-
if (debouncedSaveSignal != null) {
229-
debouncedSaveSignal.onComplete();
226+
if (debounceSaver != null) {
227+
debounceSaver.getDebouncedSaveSignal().onComplete();
230228
}
231229
if (disposables != null) {
232230
disposables.dispose();
233231
}
234232

235-
debouncedSaveSignal = null;
233+
debounceSaver = null;
236234
disposables = null;
237235
localPlaylistManager = null;
238236
remotePlaylistManager = null;
239237
itemsListState = null;
240238

241239
isLoadingComplete = null;
242-
isModified = null;
243240
displayIndexInDatabase = null;
244241
}
245242

@@ -263,7 +260,7 @@ public void onSubscribe(final Subscription s) {
263260

264261
@Override
265262
public void onNext(final List<PlaylistLocalItem> subscriptions) {
266-
if (isModified == null || !isModified.get()) {
263+
if (debounceSaver == null || !debounceSaver.getIsModified()) {
267264
checkDisplayIndexModified(subscriptions);
268265
handleResult(subscriptions);
269266
isLoadingComplete.set(true);
@@ -346,20 +343,21 @@ private void deleteItem(final PlaylistLocalItem item) {
346343
}
347344
itemListAdapter.removeItem(item);
348345

349-
saveChanges();
346+
debounceSaver.saveChanges();
350347
}
351348

352349
private void checkDisplayIndexModified(@NonNull final List<PlaylistLocalItem> result) {
353-
if (isModified != null && isModified.get()) {
350+
if (debounceSaver != null && debounceSaver.getIsModified()) {
354351
return;
355352
}
356353

357354
displayIndexInDatabase.clear();
358355

359356
// If the display index does not match actual index in the list, update the display index.
360357
// This may happen when a new list is created
361-
// or on the first run after database update
362-
// or displayIndex is not continuous for some reason.
358+
// or on the first run after database migration
359+
// or display index is not continuous for some reason
360+
// or the user changes the display index.
363361
boolean isDisplayIndexModified = false;
364362
for (int i = 0; i < result.size(); i++) {
365363
final PlaylistLocalItem item = result.get(i);
@@ -388,40 +386,19 @@ private void checkDisplayIndexModified(@NonNull final List<PlaylistLocalItem> re
388386
}
389387

390388
if (isDisplayIndexModified) {
391-
saveChanges();
392-
}
393-
}
394-
395-
private void saveChanges() {
396-
if (isModified == null || debouncedSaveSignal == null) {
397-
return;
389+
debounceSaver.saveChanges();
398390
}
399-
400-
isModified.set(true);
401-
debouncedSaveSignal.onNext(System.currentTimeMillis());
402391
}
403392

404-
private Disposable getDebouncedSaver() {
405-
if (debouncedSaveSignal == null) {
406-
return Disposable.empty();
407-
}
408-
409-
return debouncedSaveSignal
410-
.debounce(SAVE_DEBOUNCE_MILLIS, TimeUnit.MILLISECONDS)
411-
.observeOn(AndroidSchedulers.mainThread())
412-
.subscribe(ignored -> saveImmediate(), throwable ->
413-
showError(new ErrorInfo(throwable, UserAction.SOMETHING_ELSE,
414-
"Debounced saver")));
415-
}
416-
417-
private void saveImmediate() {
393+
@Override
394+
public void saveImmediate() {
418395
if (itemListAdapter == null) {
419396
return;
420397
}
421398

422399
// List must be loaded and modified in order to save
423-
if (isLoadingComplete == null || isModified == null
424-
|| !isLoadingComplete.get() || !isModified.get()) {
400+
if (isLoadingComplete == null || debounceSaver == null
401+
|| !isLoadingComplete.get() || !debounceSaver.getIsModified()) {
425402
Log.w(TAG, "Attempting to save playlists in bookmark when bookmark "
426403
+ "is not loaded or playlists not modified");
427404
return;
@@ -485,8 +462,8 @@ private void saveImmediate() {
485462
remoteItemsUpdate, remoteItemsDeleteUid)
486463
.observeOn(AndroidSchedulers.mainThread())
487464
.subscribe(() -> {
488-
if (isModified != null) {
489-
isModified.set(false);
465+
if (debounceSaver != null) {
466+
debounceSaver.setIsModified(false);
490467
}
491468
},
492469
throwable -> showError(new ErrorInfo(throwable,
@@ -544,7 +521,7 @@ public boolean onMove(@NonNull final RecyclerView recyclerView,
544521
final int targetIndex = target.getBindingAdapterPosition();
545522
final boolean isSwapped = itemListAdapter.swapItems(sourceIndex, targetIndex);
546523
if (isSwapped) {
547-
saveChanges();
524+
debounceSaver.saveChanges();
548525
}
549526
return isSwapped;
550527
}

0 commit comments

Comments
 (0)