mirror of
https://github.com/TeamNewPipe/NewPipe.git
synced 2025-10-06 03:50:22 +02:00
Merge pull request #9523 from Jared234/9468_permanently_set_thumbnail
Allow the user to permanently set a thumbnail
This commit is contained in:
commit
fd8e92cf77
12 changed files with 879 additions and 33 deletions
|
@ -5,6 +5,7 @@ import static org.schabi.newpipe.database.Migrations.MIGRATION_1_2;
|
|||
import static org.schabi.newpipe.database.Migrations.MIGRATION_2_3;
|
||||
import static org.schabi.newpipe.database.Migrations.MIGRATION_3_4;
|
||||
import static org.schabi.newpipe.database.Migrations.MIGRATION_4_5;
|
||||
import static org.schabi.newpipe.database.Migrations.MIGRATION_5_6;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
|
@ -24,7 +25,8 @@ public final class NewPipeDatabase {
|
|||
private static AppDatabase getDatabase(final Context context) {
|
||||
return Room
|
||||
.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME)
|
||||
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5)
|
||||
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5,
|
||||
MIGRATION_5_6)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.schabi.newpipe.database;
|
||||
|
||||
import static org.schabi.newpipe.database.Migrations.DB_VER_5;
|
||||
import static org.schabi.newpipe.database.Migrations.DB_VER_6;
|
||||
|
||||
import androidx.room.Database;
|
||||
import androidx.room.RoomDatabase;
|
||||
|
@ -38,7 +38,7 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
|||
FeedEntity.class, FeedGroupEntity.class, FeedGroupSubscriptionEntity.class,
|
||||
FeedLastUpdatedEntity.class
|
||||
},
|
||||
version = DB_VER_5
|
||||
version = DB_VER_6
|
||||
)
|
||||
public abstract class AppDatabase extends RoomDatabase {
|
||||
public static final String DATABASE_NAME = "newpipe.db";
|
||||
|
|
|
@ -23,6 +23,7 @@ public final class Migrations {
|
|||
public static final int DB_VER_3 = 3;
|
||||
public static final int DB_VER_4 = 4;
|
||||
public static final int DB_VER_5 = 5;
|
||||
public static final int DB_VER_6 = 6;
|
||||
|
||||
private static final String TAG = Migrations.class.getName();
|
||||
public static final boolean DEBUG = MainActivity.DEBUG;
|
||||
|
@ -188,6 +189,14 @@ public final class Migrations {
|
|||
}
|
||||
};
|
||||
|
||||
public static final Migration MIGRATION_5_6 = new Migration(DB_VER_5, DB_VER_6) {
|
||||
@Override
|
||||
public void migrate(@NonNull final SupportSQLiteDatabase database) {
|
||||
database.execSQL("ALTER TABLE `playlists` ADD COLUMN `is_thumbnail_permanent` "
|
||||
+ "INTEGER NOT NULL DEFAULT 0");
|
||||
}
|
||||
};
|
||||
|
||||
private Migrations() {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.JO
|
|||
import static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.PLAYLIST_STREAM_JOIN_TABLE;
|
||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_ID;
|
||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_TABLE;
|
||||
import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_THUMBNAIL_URL;
|
||||
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID_ALIAS;
|
||||
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_PROGRESS_MILLIS;
|
||||
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
|
||||
|
@ -53,6 +54,15 @@ public interface PlaylistStreamDAO extends BasicDAO<PlaylistStreamEntity> {
|
|||
+ " WHERE " + JOIN_PLAYLIST_ID + " = :playlistId")
|
||||
Flowable<Integer> getMaximumIndexOf(long playlistId);
|
||||
|
||||
@Query("SELECT CASE WHEN COUNT(*) != 0 then " + STREAM_THUMBNAIL_URL + " ELSE :defaultUrl END"
|
||||
+ " FROM " + STREAM_TABLE
|
||||
+ " LEFT JOIN " + PLAYLIST_STREAM_JOIN_TABLE
|
||||
+ " ON " + STREAM_ID + " = " + JOIN_STREAM_ID
|
||||
+ " WHERE " + JOIN_PLAYLIST_ID + " = :playlistId "
|
||||
+ " LIMIT 1"
|
||||
)
|
||||
Flowable<String> getAutomaticThumbnailUrl(long playlistId, String defaultUrl);
|
||||
|
||||
@RewriteQueriesToDropUnusedColumns
|
||||
@Transaction
|
||||
@Query("SELECT * FROM " + STREAM_TABLE + " INNER JOIN "
|
||||
|
|
|
@ -15,6 +15,7 @@ public class PlaylistEntity {
|
|||
public static final String PLAYLIST_ID = "uid";
|
||||
public static final String PLAYLIST_NAME = "name";
|
||||
public static final String PLAYLIST_THUMBNAIL_URL = "thumbnail_url";
|
||||
public static final String PLAYLIST_THUMBNAIL_PERMANENT = "is_thumbnail_permanent";
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo(name = PLAYLIST_ID)
|
||||
|
@ -26,9 +27,14 @@ public class PlaylistEntity {
|
|||
@ColumnInfo(name = PLAYLIST_THUMBNAIL_URL)
|
||||
private String thumbnailUrl;
|
||||
|
||||
public PlaylistEntity(final String name, final String thumbnailUrl) {
|
||||
@ColumnInfo(name = PLAYLIST_THUMBNAIL_PERMANENT)
|
||||
private boolean isThumbnailPermanent;
|
||||
|
||||
public PlaylistEntity(final String name, final String thumbnailUrl,
|
||||
final boolean isThumbnailPermanent) {
|
||||
this.name = name;
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
this.isThumbnailPermanent = isThumbnailPermanent;
|
||||
}
|
||||
|
||||
public long getUid() {
|
||||
|
@ -54,4 +60,13 @@ public class PlaylistEntity {
|
|||
public void setThumbnailUrl(final String thumbnailUrl) {
|
||||
this.thumbnailUrl = thumbnailUrl;
|
||||
}
|
||||
|
||||
public boolean getIsThumbnailPermanent() {
|
||||
return isThumbnailPermanent;
|
||||
}
|
||||
|
||||
public void setIsThumbnailPermanent(final boolean isThumbnailSet) {
|
||||
this.isThumbnailPermanent = isThumbnailSet;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.schabi.newpipe.local.bookmark;
|
||||
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.text.InputType;
|
||||
|
@ -31,6 +32,7 @@ import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
|
|||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.OnClickGesture;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import icepick.State;
|
||||
|
@ -256,6 +258,41 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||
}
|
||||
|
||||
private void showLocalDialog(final PlaylistMetadataEntry selectedItem) {
|
||||
final String rename = getString(R.string.rename);
|
||||
final String delete = getString(R.string.delete);
|
||||
final String unsetThumbnail = getString(R.string.unset_playlist_thumbnail);
|
||||
final boolean isThumbnailPermanent = localPlaylistManager
|
||||
.getIsPlaylistThumbnailPermanent(selectedItem.uid);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
|
||||
final ArrayList<String> items = new ArrayList<>();
|
||||
items.add(rename);
|
||||
items.add(delete);
|
||||
if (isThumbnailPermanent) {
|
||||
items.add(unsetThumbnail);
|
||||
}
|
||||
|
||||
final DialogInterface.OnClickListener action = (d, index) -> {
|
||||
if (items.get(index).equals(rename)) {
|
||||
showRenameDialog(selectedItem);
|
||||
} else if (items.get(index).equals(delete)) {
|
||||
showDeleteDialog(selectedItem.name,
|
||||
localPlaylistManager.deletePlaylist(selectedItem.uid));
|
||||
} else if (isThumbnailPermanent && items.get(index).equals(unsetThumbnail)) {
|
||||
final String thumbnailUrl = localPlaylistManager
|
||||
.getAutomaticPlaylistThumbnail(selectedItem.uid);
|
||||
localPlaylistManager
|
||||
.changePlaylistThumbnail(selectedItem.uid, thumbnailUrl, false)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe();
|
||||
}
|
||||
};
|
||||
|
||||
builder.setItems(items.toArray(new String[0]), action).create().show();
|
||||
}
|
||||
|
||||
private void showRenameDialog(final PlaylistMetadataEntry selectedItem) {
|
||||
final DialogEditTextBinding dialogBinding =
|
||||
DialogEditTextBinding.inflate(getLayoutInflater());
|
||||
dialogBinding.dialogEditText.setHint(R.string.name);
|
||||
|
@ -269,11 +306,6 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||
selectedItem.uid,
|
||||
dialogBinding.dialogEditText.getText().toString()))
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setNeutralButton(R.string.delete, (dialog, which) -> {
|
||||
showDeleteDialog(selectedItem.name,
|
||||
localPlaylistManager.deletePlaylist(selectedItem.uid));
|
||||
dialog.dismiss();
|
||||
})
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
|
|||
if (playlist.thumbnailUrl
|
||||
.equals("drawable://" + R.drawable.placeholder_thumbnail_playlist)) {
|
||||
playlistDisposables.add(manager
|
||||
.changePlaylistThumbnail(playlist.uid, streams.get(0).getThumbnailUrl())
|
||||
.changePlaylistThumbnail(playlist.uid, streams.get(0).getThumbnailUrl(), false)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(ignored -> successToast.show()));
|
||||
}
|
||||
|
|
|
@ -405,6 +405,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
.zipWith(historyIdsMaybe, (playlist, historyStreamIds) -> {
|
||||
// Remove Watched, Functionality data
|
||||
final List<PlaylistStreamEntry> notWatchedItems = new ArrayList<>();
|
||||
final boolean isThumbnailPermanent = playlistManager
|
||||
.getIsPlaylistThumbnailPermanent(playlistId);
|
||||
boolean thumbnailVideoRemoved = false;
|
||||
|
||||
if (removePartiallyWatched) {
|
||||
|
@ -414,7 +416,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
|
||||
if (indexInHistory < 0) {
|
||||
notWatchedItems.add(playlistItem);
|
||||
} else if (!thumbnailVideoRemoved
|
||||
} else if (!isThumbnailPermanent && !thumbnailVideoRemoved
|
||||
&& playlistManager.getPlaylistThumbnail(playlistId)
|
||||
.equals(playlistItem.getStreamEntity().getThumbnailUrl())) {
|
||||
thumbnailVideoRemoved = true;
|
||||
|
@ -435,7 +437,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
if (indexInHistory < 0 || (streamStateEntity != null
|
||||
&& !streamStateEntity.isFinished(duration))) {
|
||||
notWatchedItems.add(playlistItem);
|
||||
} else if (!thumbnailVideoRemoved
|
||||
} else if (!isThumbnailPermanent && !thumbnailVideoRemoved
|
||||
&& playlistManager.getPlaylistThumbnail(playlistId)
|
||||
.equals(playlistItem.getStreamEntity().getThumbnailUrl())) {
|
||||
thumbnailVideoRemoved = true;
|
||||
|
@ -585,8 +587,9 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
disposables.add(disposable);
|
||||
}
|
||||
|
||||
private void changeThumbnailUrl(final String thumbnailUrl) {
|
||||
if (playlistManager == null) {
|
||||
private void changeThumbnailUrl(final String thumbnailUrl, final boolean isPermanent) {
|
||||
if (playlistManager == null || (!isPermanent && playlistManager
|
||||
.getIsPlaylistThumbnailPermanent(playlistId))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -600,7 +603,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
}
|
||||
|
||||
final Disposable disposable = playlistManager
|
||||
.changePlaylistThumbnail(playlistId, thumbnailUrl)
|
||||
.changePlaylistThumbnail(playlistId, thumbnailUrl, isPermanent)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(ignore -> successToast.show(), throwable ->
|
||||
showError(new ErrorInfo(throwable, UserAction.REQUESTED_BOOKMARK,
|
||||
|
@ -609,6 +612,10 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
}
|
||||
|
||||
private void updateThumbnailUrl() {
|
||||
if (playlistManager.getIsPlaylistThumbnailPermanent(playlistId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String newThumbnailUrl;
|
||||
|
||||
if (!itemListAdapter.getItemsList().isEmpty()) {
|
||||
|
@ -618,7 +625,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
newThumbnailUrl = "drawable://" + R.drawable.placeholder_thumbnail_playlist;
|
||||
}
|
||||
|
||||
changeThumbnailUrl(newThumbnailUrl);
|
||||
changeThumbnailUrl(newThumbnailUrl, false);
|
||||
}
|
||||
|
||||
private void deleteItem(final PlaylistStreamEntry item) {
|
||||
|
@ -786,7 +793,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
.setAction(
|
||||
StreamDialogDefaultEntry.SET_AS_PLAYLIST_THUMBNAIL,
|
||||
(f, i) ->
|
||||
changeThumbnailUrl(item.getStreamEntity().getThumbnailUrl()))
|
||||
changeThumbnailUrl(item.getStreamEntity().getThumbnailUrl(),
|
||||
true))
|
||||
.setAction(
|
||||
StreamDialogDefaultEntry.DELETE,
|
||||
(f, i) -> deleteItem(item))
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.schabi.newpipe.local.playlist;
|
|||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.database.AppDatabase;
|
||||
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
|
||||
import org.schabi.newpipe.database.playlist.PlaylistStreamEntry;
|
||||
|
@ -41,7 +42,7 @@ public class LocalPlaylistManager {
|
|||
}
|
||||
final StreamEntity defaultStream = streams.get(0);
|
||||
final PlaylistEntity newPlaylist =
|
||||
new PlaylistEntity(name, defaultStream.getThumbnailUrl());
|
||||
new PlaylistEntity(name, defaultStream.getThumbnailUrl(), false);
|
||||
|
||||
return Maybe.fromCallable(() -> database.runInTransaction(() ->
|
||||
upsertStreams(playlistTable.insert(newPlaylist), streams, 0))
|
||||
|
@ -96,21 +97,33 @@ public class LocalPlaylistManager {
|
|||
}
|
||||
|
||||
public Maybe<Integer> renamePlaylist(final long playlistId, final String name) {
|
||||
return modifyPlaylist(playlistId, name, null);
|
||||
return modifyPlaylist(playlistId, name, null, false);
|
||||
}
|
||||
|
||||
public Maybe<Integer> changePlaylistThumbnail(final long playlistId,
|
||||
final String thumbnailUrl) {
|
||||
return modifyPlaylist(playlistId, null, thumbnailUrl);
|
||||
final String thumbnailUrl,
|
||||
final boolean isPermanent) {
|
||||
return modifyPlaylist(playlistId, null, thumbnailUrl, isPermanent);
|
||||
}
|
||||
|
||||
public String getPlaylistThumbnail(final long playlistId) {
|
||||
return playlistTable.getPlaylist(playlistId).blockingFirst().get(0).getThumbnailUrl();
|
||||
}
|
||||
|
||||
public boolean getIsPlaylistThumbnailPermanent(final long playlistId) {
|
||||
return playlistTable.getPlaylist(playlistId).blockingFirst().get(0)
|
||||
.getIsThumbnailPermanent();
|
||||
}
|
||||
|
||||
public String getAutomaticPlaylistThumbnail(final long playlistId) {
|
||||
final String def = "drawable://" + R.drawable.placeholder_thumbnail_playlist;
|
||||
return playlistStreamTable.getAutomaticThumbnailUrl(playlistId, def).blockingFirst();
|
||||
}
|
||||
|
||||
private Maybe<Integer> modifyPlaylist(final long playlistId,
|
||||
@Nullable final String name,
|
||||
@Nullable final String thumbnailUrl) {
|
||||
@Nullable final String thumbnailUrl,
|
||||
final boolean isPermanent) {
|
||||
return playlistTable.getPlaylist(playlistId)
|
||||
.firstElement()
|
||||
.filter(playlistEntities -> !playlistEntities.isEmpty())
|
||||
|
@ -121,6 +134,7 @@ public class LocalPlaylistManager {
|
|||
}
|
||||
if (thumbnailUrl != null) {
|
||||
playlist.setThumbnailUrl(thumbnailUrl);
|
||||
playlist.setIsThumbnailPermanent(isPermanent);
|
||||
}
|
||||
return playlistTable.update(playlist);
|
||||
}).subscribeOn(Schedulers.io());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue