Save changes to the database and bugfix
This commit is contained in:
parent
813f55152a
commit
ba8370bcfd
7 changed files with 100 additions and 10 deletions
|
@ -24,6 +24,12 @@ public interface PlaylistLocalItem extends LocalItem {
|
||||||
final List<PlaylistLocalItem> result = new ArrayList<>(
|
final List<PlaylistLocalItem> result = new ArrayList<>(
|
||||||
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 displayIndex 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()) {
|
||||||
|
@ -41,10 +47,6 @@ public interface PlaylistLocalItem extends LocalItem {
|
||||||
}
|
}
|
||||||
addItemsWithSameIndex(result, itemsWithSameIndex);
|
addItemsWithSameIndex(result, itemsWithSameIndex);
|
||||||
|
|
||||||
// If displayIndex does not match actual index, update displayIndex.
|
|
||||||
// This may happen when a new list is created with default displayIndex = 0.
|
|
||||||
// todo: update displayIndex
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +54,8 @@ public interface PlaylistLocalItem extends LocalItem {
|
||||||
final List<PlaylistLocalItem> itemsWithSameIndex) {
|
final List<PlaylistLocalItem> itemsWithSameIndex) {
|
||||||
if (!itemsWithSameIndex.isEmpty()
|
if (!itemsWithSameIndex.isEmpty()
|
||||||
&& itemsWithSameIndex.get(0).getDisplayIndex() != item.getDisplayIndex()) {
|
&& itemsWithSameIndex.get(0).getDisplayIndex() != item.getDisplayIndex()) {
|
||||||
// The new item has a different displayIndex,
|
// The new item has a different displayIndex, add previous items with same
|
||||||
// add previous items with same index to the result.
|
// index to the result.
|
||||||
addItemsWithSameIndex(result, itemsWithSameIndex);
|
addItemsWithSameIndex(result, itemsWithSameIndex);
|
||||||
itemsWithSameIndex.clear();
|
itemsWithSameIndex.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,10 @@ public interface PlaylistRemoteDAO extends BasicDAO<PlaylistRemoteEntity> {
|
||||||
+ " WHERE " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId")
|
+ " WHERE " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId")
|
||||||
Flowable<List<PlaylistRemoteEntity>> listByService(int serviceId);
|
Flowable<List<PlaylistRemoteEntity>> listByService(int serviceId);
|
||||||
|
|
||||||
|
@Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE + " WHERE "
|
||||||
|
+ REMOTE_PLAYLIST_ID + " = :playlistId")
|
||||||
|
Flowable<List<PlaylistRemoteEntity>> getPlaylist(long playlistId);
|
||||||
|
|
||||||
@Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE + " WHERE "
|
@Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE + " WHERE "
|
||||||
+ 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);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.schabi.newpipe.database.playlist.model;
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
import androidx.room.ColumnInfo;
|
||||||
import androidx.room.Entity;
|
import androidx.room.Entity;
|
||||||
|
import androidx.room.Ignore;
|
||||||
import androidx.room.Index;
|
import androidx.room.Index;
|
||||||
import androidx.room.PrimaryKey;
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
@ -28,11 +29,12 @@ public class PlaylistEntity {
|
||||||
private String thumbnailUrl;
|
private String thumbnailUrl;
|
||||||
|
|
||||||
@ColumnInfo(name = PLAYLIST_DISPLAY_INDEX)
|
@ColumnInfo(name = PLAYLIST_DISPLAY_INDEX)
|
||||||
private long displayIndex = 0;
|
private long displayIndex;
|
||||||
|
|
||||||
public PlaylistEntity(final String name, final String thumbnailUrl) {
|
public PlaylistEntity(final String name, final String thumbnailUrl, final long displayIndex) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.thumbnailUrl = thumbnailUrl;
|
this.thumbnailUrl = thumbnailUrl;
|
||||||
|
this.displayIndex = displayIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getUid() {
|
public long getUid() {
|
||||||
|
|
|
@ -142,6 +142,7 @@ public class LocalItemListAdapter extends RecyclerView.Adapter<RecyclerView.View
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean swapItems(final int fromAdapterPosition, final int toAdapterPosition) {
|
public boolean swapItems(final int fromAdapterPosition, final int toAdapterPosition) {
|
||||||
|
// todo: reuse this code?
|
||||||
final int actualFrom = adapterOffsetWithoutHeader(fromAdapterPosition);
|
final int actualFrom = adapterOffsetWithoutHeader(fromAdapterPosition);
|
||||||
final int actualTo = adapterOffsetWithoutHeader(toAdapterPosition);
|
final int actualTo = adapterOffsetWithoutHeader(toAdapterPosition);
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,13 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNext(final List<PlaylistLocalItem> subscriptions) {
|
public void onNext(final List<PlaylistLocalItem> subscriptions) {
|
||||||
|
|
||||||
|
// If displayIndex does not match actual index, update displayIndex.
|
||||||
|
// This may happen when a new list is created
|
||||||
|
// or on the first run after database update
|
||||||
|
// or displayIndex is not continuous for some reason.
|
||||||
|
checkDisplayIndexUpdate(subscriptions);
|
||||||
|
|
||||||
handleResult(subscriptions);
|
handleResult(subscriptions);
|
||||||
if (databaseSubscription != null) {
|
if (databaseSubscription != null) {
|
||||||
databaseSubscription.request(1);
|
databaseSubscription.request(1);
|
||||||
|
@ -212,7 +219,8 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onComplete() { }
|
public void onComplete() {
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,5 +324,60 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
||||||
"Changing playlist name")));
|
"Changing playlist name")));
|
||||||
disposables.add(disposable);
|
disposables.add(disposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void changeLocalPlaylistDisplayIndex(final long id, final long displayIndex) {
|
||||||
|
|
||||||
|
if (localPlaylistManager == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "Updating local playlist id=[" + id + "] "
|
||||||
|
+ "with new display_index=[" + displayIndex + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Disposable disposable =
|
||||||
|
localPlaylistManager.changePlaylistDisplayIndex(id, displayIndex)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(longs -> { /*Do nothing on success*/ }, throwable -> showError(
|
||||||
|
new ErrorInfo(throwable,
|
||||||
|
UserAction.REQUESTED_BOOKMARK,
|
||||||
|
"Changing local playlist display_index")));
|
||||||
|
disposables.add(disposable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeRemotePlaylistDisplayIndex(final long id, final long displayIndex) {
|
||||||
|
|
||||||
|
if (remotePlaylistManager == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Log.d(TAG, "Updating remote playlist id=[" + id + "] "
|
||||||
|
+ "with new display_index=[" + displayIndex + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Disposable disposable =
|
||||||
|
remotePlaylistManager.changePlaylistDisplayIndex(id, displayIndex)
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(longs -> { /*Do nothing on success*/ }, throwable -> showError(
|
||||||
|
new ErrorInfo(throwable,
|
||||||
|
UserAction.REQUESTED_BOOKMARK,
|
||||||
|
"Changing remote playlist display_index")));
|
||||||
|
disposables.add(disposable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkDisplayIndexUpdate(@NonNull final List<PlaylistLocalItem> result) {
|
||||||
|
for (int i = 0; i < result.size(); i++) {
|
||||||
|
final PlaylistLocalItem item = result.get(i);
|
||||||
|
if (item.getDisplayIndex() != i) {
|
||||||
|
if (item instanceof PlaylistMetadataEntry) {
|
||||||
|
changeLocalPlaylistDisplayIndex(((PlaylistMetadataEntry) item).uid, i);
|
||||||
|
} else if (item instanceof PlaylistRemoteEntity) {
|
||||||
|
changeRemotePlaylistDisplayIndex(((PlaylistRemoteEntity) item).getUid(), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,11 @@ public class LocalPlaylistManager {
|
||||||
return Maybe.empty();
|
return Maybe.empty();
|
||||||
}
|
}
|
||||||
final StreamEntity defaultStream = streams.get(0);
|
final StreamEntity defaultStream = streams.get(0);
|
||||||
|
|
||||||
|
// Make sure the new playlist is always on the top of bookmark.
|
||||||
|
// The index will be reassigned to non-negative number in BookmarkFragment.
|
||||||
final PlaylistEntity newPlaylist =
|
final PlaylistEntity newPlaylist =
|
||||||
new PlaylistEntity(name, defaultStream.getThumbnailUrl());
|
new PlaylistEntity(name, defaultStream.getThumbnailUrl(), -1);
|
||||||
|
|
||||||
return Maybe.fromCallable(() -> database.runInTransaction(() ->
|
return Maybe.fromCallable(() -> database.runInTransaction(() ->
|
||||||
upsertStreams(playlistTable.insert(newPlaylist), streams, 0))
|
upsertStreams(playlistTable.insert(newPlaylist), streams, 0))
|
||||||
|
|
|
@ -8,6 +8,7 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import io.reactivex.rxjava3.core.Flowable;
|
import io.reactivex.rxjava3.core.Flowable;
|
||||||
|
import io.reactivex.rxjava3.core.Maybe;
|
||||||
import io.reactivex.rxjava3.core.Single;
|
import io.reactivex.rxjava3.core.Single;
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
|
||||||
|
@ -33,6 +34,20 @@ public class RemotePlaylistManager {
|
||||||
.subscribeOn(Schedulers.io());
|
.subscribeOn(Schedulers.io());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Maybe<Integer> changePlaylistDisplayIndex(final long playlistId,
|
||||||
|
final long displayIndex) {
|
||||||
|
return playlistRemoteTable.getPlaylist(playlistId)
|
||||||
|
.firstElement()
|
||||||
|
.filter(playlistRemoteEntities -> !playlistRemoteEntities.isEmpty())
|
||||||
|
.map(playlistRemoteEntities -> {
|
||||||
|
final PlaylistRemoteEntity playlist = playlistRemoteEntities.get(0);
|
||||||
|
if (displayIndex != -1) {
|
||||||
|
playlist.setDisplayIndex(displayIndex);
|
||||||
|
}
|
||||||
|
return playlistRemoteTable.update(playlist);
|
||||||
|
}).subscribeOn(Schedulers.io());
|
||||||
|
}
|
||||||
|
|
||||||
public Single<Long> onBookmark(final PlaylistInfo playlistInfo) {
|
public Single<Long> onBookmark(final PlaylistInfo playlistInfo) {
|
||||||
return Single.fromCallable(() -> {
|
return Single.fromCallable(() -> {
|
||||||
final PlaylistRemoteEntity playlist = new PlaylistRemoteEntity(playlistInfo);
|
final PlaylistRemoteEntity playlist = new PlaylistRemoteEntity(playlistInfo);
|
||||||
|
|
Loading…
Reference in a new issue