Create sub-package and default interval for DebounceSaver & sort playlists in db
This commit is contained in:
parent
6526ff1612
commit
d32490a4be
8 changed files with 35 additions and 17 deletions
|
@ -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()) {
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
Loading…
Reference in a new issue