Save changes to the database and bugfix

This commit is contained in:
GGAutomaton 2022-04-14 12:13:42 +08:00
parent 813f55152a
commit ba8370bcfd
7 changed files with 100 additions and 10 deletions

View File

@ -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();
} }

View File

@ -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);

View File

@ -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() {

View File

@ -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);

View File

@ -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);
}
}
}
}
} }

View File

@ -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))

View File

@ -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);