Create sub-package and default interval for DebounceSaver & sort playlists in db

This commit is contained in:
GGAutomaton 2022-05-11 16:47:34 +08:00
parent 6526ff1612
commit d32490a4be
8 changed files with 35 additions and 17 deletions

View file

@ -16,6 +16,7 @@ public interface PlaylistLocalItem extends LocalItem {
static List<PlaylistLocalItem> merge( static List<PlaylistLocalItem> merge(
final List<PlaylistMetadataEntry> localPlaylists, final List<PlaylistMetadataEntry> localPlaylists,
final List<PlaylistRemoteEntity> remotePlaylists) { final List<PlaylistRemoteEntity> remotePlaylists) {
// The playlists from the database must be in the display index order.
// Merge localPlaylists and remotePlaylists by display index. // Merge localPlaylists and remotePlaylists by display index.
// If two items have the same display index, sort them in CASE_INSENSITIVE_ORDER. // If two items have the same display index, sort them in CASE_INSENSITIVE_ORDER.
@ -25,11 +26,6 @@ public interface PlaylistLocalItem extends LocalItem {
localPlaylists.size() + remotePlaylists.size()); localPlaylists.size() + remotePlaylists.size());
final List<PlaylistLocalItem> itemsWithSameIndex = new ArrayList<>(); final List<PlaylistLocalItem> itemsWithSameIndex = new ArrayList<>();
// The data from database may not be in the display index order
Collections.sort(localPlaylists,
Comparator.comparingLong(PlaylistMetadataEntry::getDisplayIndex));
Collections.sort(remotePlaylists,
Comparator.comparingLong(PlaylistRemoteEntity::getDisplayIndex));
int i = 0; int i = 0;
int j = 0; int j = 0;
while (i < localPlaylists.size()) { while (i < localPlaylists.size()) {

View file

@ -11,6 +11,7 @@ import java.util.List;
import io.reactivex.rxjava3.core.Flowable; import io.reactivex.rxjava3.core.Flowable;
import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_DISPLAY_INDEX;
import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_ID; import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_ID;
import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_SERVICE_ID; import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_SERVICE_ID;
import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_TABLE; import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_TABLE;
@ -39,6 +40,10 @@ public interface PlaylistRemoteDAO extends BasicDAO<PlaylistRemoteEntity> {
+ REMOTE_PLAYLIST_URL + " = :url AND " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId") + REMOTE_PLAYLIST_URL + " = :url AND " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId")
Flowable<List<PlaylistRemoteEntity>> getPlaylist(long serviceId, String url); Flowable<List<PlaylistRemoteEntity>> getPlaylist(long serviceId, String url);
@Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE
+ " ORDER BY " + REMOTE_PLAYLIST_DISPLAY_INDEX)
Flowable<List<PlaylistRemoteEntity>> getDisplayIndexOrderedPlaylists();
@Query("SELECT " + REMOTE_PLAYLIST_ID + " FROM " + REMOTE_PLAYLIST_TABLE @Query("SELECT " + REMOTE_PLAYLIST_ID + " FROM " + REMOTE_PLAYLIST_TABLE
+ " WHERE " + REMOTE_PLAYLIST_URL + " = :url " + " WHERE " + REMOTE_PLAYLIST_URL + " = :url "
+ "AND " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId") + "AND " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId")

View file

@ -35,8 +35,8 @@ import org.schabi.newpipe.local.holder.LocalBookmarkPlaylistItemHolder;
import org.schabi.newpipe.local.holder.RemoteBookmarkPlaylistItemHolder; import org.schabi.newpipe.local.holder.RemoteBookmarkPlaylistItemHolder;
import org.schabi.newpipe.local.playlist.LocalPlaylistManager; import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
import org.schabi.newpipe.local.playlist.RemotePlaylistManager; import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
import org.schabi.newpipe.util.DebounceSavable; import org.schabi.newpipe.util.debounce.DebounceSavable;
import org.schabi.newpipe.util.DebounceSaver; import org.schabi.newpipe.util.debounce.DebounceSaver;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture; import org.schabi.newpipe.util.OnClickGesture;
@ -89,7 +89,7 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
disposables = new CompositeDisposable(); disposables = new CompositeDisposable();
isLoadingComplete = new AtomicBoolean(); isLoadingComplete = new AtomicBoolean();
debounceSaver = new DebounceSaver(10000, this); debounceSaver = new DebounceSaver(this);
displayIndexInDatabase = new HashMap<>(); displayIndexInDatabase = new HashMap<>();
} }
@ -185,8 +185,8 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
} }
isLoadingComplete.set(false); isLoadingComplete.set(false);
Flowable.combineLatest(localPlaylistManager.getPlaylists(), Flowable.combineLatest(localPlaylistManager.getDisplayIndexOrderedPlaylists(),
remotePlaylistManager.getPlaylists(), PlaylistLocalItem::merge) remotePlaylistManager.getDisplayIndexOrderedPlaylists(), PlaylistLocalItem::merge)
.onBackpressureLatest() .onBackpressureLatest()
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(getPlaylistsSubscriber()); .subscribe(getPlaylistsSubscriber());

View file

@ -46,8 +46,8 @@ import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.player.MainPlayer.PlayerType; import org.schabi.newpipe.player.MainPlayer.PlayerType;
import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.util.DebounceSavable; import org.schabi.newpipe.util.debounce.DebounceSavable;
import org.schabi.newpipe.util.DebounceSaver; import org.schabi.newpipe.util.debounce.DebounceSaver;
import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture; import org.schabi.newpipe.util.OnClickGesture;
@ -112,7 +112,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
disposables = new CompositeDisposable(); disposables = new CompositeDisposable();
isLoadingComplete = new AtomicBoolean(); isLoadingComplete = new AtomicBoolean();
debounceSaver = new DebounceSaver(10000, this); debounceSaver = new DebounceSaver(this);
} }
@Override @Override

View file

@ -26,6 +26,10 @@ public class RemotePlaylistManager {
return playlistRemoteTable.getAll().subscribeOn(Schedulers.io()); return playlistRemoteTable.getAll().subscribeOn(Schedulers.io());
} }
public Flowable<List<PlaylistRemoteEntity>> getDisplayIndexOrderedPlaylists() {
return playlistRemoteTable.getDisplayIndexOrderedPlaylists().subscribeOn(Schedulers.io());
}
public Flowable<List<PlaylistRemoteEntity>> getPlaylist(final PlaylistInfo info) { public Flowable<List<PlaylistRemoteEntity>> getPlaylist(final PlaylistInfo info) {
return playlistRemoteTable.getPlaylist(info.getServiceId(), info.getUrl()) return playlistRemoteTable.getPlaylist(info.getServiceId(), info.getUrl())
.subscribeOn(Schedulers.io()); .subscribeOn(Schedulers.io());

View file

@ -90,8 +90,8 @@ public class SelectPlaylistFragment extends DialogFragment {
final LocalPlaylistManager localPlaylistManager = new LocalPlaylistManager(database); final LocalPlaylistManager localPlaylistManager = new LocalPlaylistManager(database);
final RemotePlaylistManager remotePlaylistManager = new RemotePlaylistManager(database); final RemotePlaylistManager remotePlaylistManager = new RemotePlaylistManager(database);
disposable = Flowable.combineLatest(localPlaylistManager.getPlaylists(), disposable = Flowable.combineLatest(localPlaylistManager.getDisplayIndexOrderedPlaylists(),
remotePlaylistManager.getPlaylists(), PlaylistLocalItem::merge) remotePlaylistManager.getDisplayIndexOrderedPlaylists(), PlaylistLocalItem::merge)
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(this::displayPlaylists, this::onError); .subscribe(this::displayPlaylists, this::onError);
} }

View file

@ -1,4 +1,4 @@
package org.schabi.newpipe.util; package org.schabi.newpipe.util.debounce;
import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorInfo;

View file

@ -1,4 +1,4 @@
package org.schabi.newpipe.util; package org.schabi.newpipe.util.debounce;
import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.UserAction; import org.schabi.newpipe.error.UserAction;
@ -21,6 +21,9 @@ public class DebounceSaver {
// Has the object been modified // Has the object been modified
private final AtomicBoolean isModified; private final AtomicBoolean isModified;
// Default 10 seconds
private static final long DEFAULT_SAVE_DEBOUNCE_MILLIS = 10000;
/** /**
* Creates a new {@code DebounceSaver}. * Creates a new {@code DebounceSaver}.
@ -36,6 +39,16 @@ public class DebounceSaver {
this.isModified = new AtomicBoolean(); this.isModified = new AtomicBoolean();
} }
/**
* Creates a new {@code DebounceSaver}. Save the object 10 seconds later after the last change
* occurred.
*
* @param debounceSavable The object containing data to be saved.
*/
public DebounceSaver(final DebounceSavable debounceSavable) {
this(DEFAULT_SAVE_DEBOUNCE_MILLIS, debounceSavable);
}
public boolean getIsModified() { public boolean getIsModified() {
return isModified.get(); return isModified.get();
} }